diff options
Diffstat (limited to 'drivers/memory')
| -rw-r--r-- | drivers/memory/Kconfig | 1 | ||||
| -rw-r--r-- | drivers/memory/omap-gpmc.c | 117 |
2 files changed, 106 insertions, 12 deletions
diff --git a/drivers/memory/Kconfig b/drivers/memory/Kconfig index 51d5cd20c26a..a9b1c1419bef 100644 --- a/drivers/memory/Kconfig +++ b/drivers/memory/Kconfig | |||
| @@ -51,6 +51,7 @@ config TI_EMIF | |||
| 51 | 51 | ||
| 52 | config OMAP_GPMC | 52 | config OMAP_GPMC |
| 53 | bool | 53 | bool |
| 54 | select GPIOLIB | ||
| 54 | help | 55 | help |
| 55 | This driver is for the General Purpose Memory Controller (GPMC) | 56 | This driver is for the General Purpose Memory Controller (GPMC) |
| 56 | present on Texas Instruments SoCs (e.g. OMAP2+). GPMC allows | 57 | present on Texas Instruments SoCs (e.g. OMAP2+). GPMC allows |
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c index bfe4e8710973..4dd1c65ee70c 100644 --- a/drivers/memory/omap-gpmc.c +++ b/drivers/memory/omap-gpmc.c | |||
| @@ -21,6 +21,7 @@ | |||
| 21 | #include <linux/spinlock.h> | 21 | #include <linux/spinlock.h> |
| 22 | #include <linux/io.h> | 22 | #include <linux/io.h> |
| 23 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 24 | #include <linux/gpio/driver.h> | ||
| 24 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
| 25 | #include <linux/irqdomain.h> | 26 | #include <linux/irqdomain.h> |
| 26 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
| @@ -237,6 +238,7 @@ struct gpmc_device { | |||
| 237 | struct device *dev; | 238 | struct device *dev; |
| 238 | int irq; | 239 | int irq; |
| 239 | struct irq_chip irq_chip; | 240 | struct irq_chip irq_chip; |
| 241 | struct gpio_chip gpio_chip; | ||
| 240 | }; | 242 | }; |
| 241 | 243 | ||
| 242 | static struct irq_domain *gpmc_irq_domain; | 244 | static struct irq_domain *gpmc_irq_domain; |
| @@ -2064,10 +2066,71 @@ err: | |||
| 2064 | return ret; | 2066 | return ret; |
| 2065 | } | 2067 | } |
| 2066 | 2068 | ||
| 2069 | static int gpmc_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) | ||
| 2070 | { | ||
| 2071 | return 1; /* we're input only */ | ||
| 2072 | } | ||
| 2073 | |||
| 2074 | static int gpmc_gpio_direction_input(struct gpio_chip *chip, | ||
| 2075 | unsigned int offset) | ||
| 2076 | { | ||
| 2077 | return 0; /* we're input only */ | ||
| 2078 | } | ||
| 2079 | |||
| 2080 | static int gpmc_gpio_direction_output(struct gpio_chip *chip, | ||
| 2081 | unsigned int offset, int value) | ||
| 2082 | { | ||
| 2083 | return -EINVAL; /* we're input only */ | ||
| 2084 | } | ||
| 2085 | |||
| 2086 | static void gpmc_gpio_set(struct gpio_chip *chip, unsigned int offset, | ||
| 2087 | int value) | ||
| 2088 | { | ||
| 2089 | } | ||
| 2090 | |||
| 2091 | static int gpmc_gpio_get(struct gpio_chip *chip, unsigned int offset) | ||
| 2092 | { | ||
| 2093 | u32 reg; | ||
| 2094 | |||
| 2095 | offset += 8; | ||
| 2096 | |||
| 2097 | reg = gpmc_read_reg(GPMC_STATUS) & BIT(offset); | ||
| 2098 | |||
| 2099 | return !!reg; | ||
| 2100 | } | ||
| 2101 | |||
| 2102 | static int gpmc_gpio_init(struct gpmc_device *gpmc) | ||
| 2103 | { | ||
| 2104 | int ret; | ||
| 2105 | |||
| 2106 | gpmc->gpio_chip.parent = gpmc->dev; | ||
| 2107 | gpmc->gpio_chip.owner = THIS_MODULE; | ||
| 2108 | gpmc->gpio_chip.label = DEVICE_NAME; | ||
| 2109 | gpmc->gpio_chip.ngpio = gpmc_nr_waitpins; | ||
| 2110 | gpmc->gpio_chip.get_direction = gpmc_gpio_get_direction; | ||
| 2111 | gpmc->gpio_chip.direction_input = gpmc_gpio_direction_input; | ||
| 2112 | gpmc->gpio_chip.direction_output = gpmc_gpio_direction_output; | ||
| 2113 | gpmc->gpio_chip.set = gpmc_gpio_set; | ||
| 2114 | gpmc->gpio_chip.get = gpmc_gpio_get; | ||
| 2115 | gpmc->gpio_chip.base = -1; | ||
| 2116 | |||
| 2117 | ret = gpiochip_add(&gpmc->gpio_chip); | ||
| 2118 | if (ret < 0) { | ||
| 2119 | dev_err(gpmc->dev, "could not register gpio chip: %d\n", ret); | ||
| 2120 | return ret; | ||
| 2121 | } | ||
| 2122 | |||
| 2123 | return 0; | ||
| 2124 | } | ||
| 2125 | |||
| 2126 | static void gpmc_gpio_exit(struct gpmc_device *gpmc) | ||
| 2127 | { | ||
| 2128 | gpiochip_remove(&gpmc->gpio_chip); | ||
| 2129 | } | ||
| 2130 | |||
| 2067 | static int gpmc_probe_dt(struct platform_device *pdev) | 2131 | static int gpmc_probe_dt(struct platform_device *pdev) |
| 2068 | { | 2132 | { |
| 2069 | int ret; | 2133 | int ret; |
| 2070 | struct device_node *child; | ||
| 2071 | const struct of_device_id *of_id = | 2134 | const struct of_device_id *of_id = |
| 2072 | of_match_device(gpmc_dt_ids, &pdev->dev); | 2135 | of_match_device(gpmc_dt_ids, &pdev->dev); |
| 2073 | 2136 | ||
| @@ -2095,6 +2158,14 @@ static int gpmc_probe_dt(struct platform_device *pdev) | |||
| 2095 | return ret; | 2158 | return ret; |
| 2096 | } | 2159 | } |
| 2097 | 2160 | ||
| 2161 | return 0; | ||
| 2162 | } | ||
| 2163 | |||
| 2164 | static int gpmc_probe_dt_children(struct platform_device *pdev) | ||
| 2165 | { | ||
| 2166 | int ret; | ||
| 2167 | struct device_node *child; | ||
| 2168 | |||
| 2098 | for_each_available_child_of_node(pdev->dev.of_node, child) { | 2169 | for_each_available_child_of_node(pdev->dev.of_node, child) { |
| 2099 | 2170 | ||
| 2100 | if (!child->name) | 2171 | if (!child->name) |
| @@ -2104,6 +2175,9 @@ static int gpmc_probe_dt(struct platform_device *pdev) | |||
| 2104 | ret = gpmc_probe_onenand_child(pdev, child); | 2175 | ret = gpmc_probe_onenand_child(pdev, child); |
| 2105 | else | 2176 | else |
| 2106 | ret = gpmc_probe_generic_child(pdev, child); | 2177 | ret = gpmc_probe_generic_child(pdev, child); |
| 2178 | |||
| 2179 | if (ret) | ||
| 2180 | return ret; | ||
| 2107 | } | 2181 | } |
| 2108 | 2182 | ||
| 2109 | return 0; | 2183 | return 0; |
| @@ -2113,6 +2187,11 @@ static int gpmc_probe_dt(struct platform_device *pdev) | |||
| 2113 | { | 2187 | { |
| 2114 | return 0; | 2188 | return 0; |
| 2115 | } | 2189 | } |
| 2190 | |||
| 2191 | static int gpmc_probe_dt_children(struct platform_device *pdev) | ||
| 2192 | { | ||
| 2193 | return 0; | ||
| 2194 | } | ||
| 2116 | #endif | 2195 | #endif |
| 2117 | 2196 | ||
| 2118 | static int gpmc_probe(struct platform_device *pdev) | 2197 | static int gpmc_probe(struct platform_device *pdev) |
| @@ -2159,6 +2238,15 @@ static int gpmc_probe(struct platform_device *pdev) | |||
| 2159 | return -EINVAL; | 2238 | return -EINVAL; |
| 2160 | } | 2239 | } |
| 2161 | 2240 | ||
| 2241 | if (pdev->dev.of_node) { | ||
| 2242 | rc = gpmc_probe_dt(pdev); | ||
| 2243 | if (rc) | ||
| 2244 | return rc; | ||
| 2245 | } else { | ||
| 2246 | gpmc_cs_num = GPMC_CS_NUM; | ||
| 2247 | gpmc_nr_waitpins = GPMC_NR_WAITPINS; | ||
| 2248 | } | ||
| 2249 | |||
| 2162 | pm_runtime_enable(&pdev->dev); | 2250 | pm_runtime_enable(&pdev->dev); |
| 2163 | pm_runtime_get_sync(&pdev->dev); | 2251 | pm_runtime_get_sync(&pdev->dev); |
| 2164 | 2252 | ||
| @@ -2184,29 +2272,33 @@ static int gpmc_probe(struct platform_device *pdev) | |||
| 2184 | GPMC_REVISION_MINOR(l)); | 2272 | GPMC_REVISION_MINOR(l)); |
| 2185 | 2273 | ||
| 2186 | gpmc_mem_init(); | 2274 | gpmc_mem_init(); |
| 2275 | rc = gpmc_gpio_init(gpmc); | ||
| 2276 | if (rc) | ||
| 2277 | goto gpio_init_failed; | ||
| 2187 | 2278 | ||
| 2188 | rc = gpmc_setup_irq(gpmc); | 2279 | rc = gpmc_setup_irq(gpmc); |
| 2189 | if (rc) { | 2280 | if (rc) { |
| 2190 | dev_err(gpmc->dev, "gpmc_setup_irq failed\n"); | 2281 | dev_err(gpmc->dev, "gpmc_setup_irq failed\n"); |
| 2191 | goto fail; | 2282 | goto setup_irq_failed; |
| 2192 | } | 2283 | } |
| 2193 | 2284 | ||
| 2194 | if (!pdev->dev.of_node) { | 2285 | rc = gpmc_probe_dt_children(pdev); |
| 2195 | gpmc_cs_num = GPMC_CS_NUM; | ||
| 2196 | gpmc_nr_waitpins = GPMC_NR_WAITPINS; | ||
| 2197 | } | ||
| 2198 | |||
| 2199 | rc = gpmc_probe_dt(pdev); | ||
| 2200 | if (rc < 0) { | 2286 | if (rc < 0) { |
| 2201 | dev_err(gpmc->dev, "failed to probe DT parameters\n"); | 2287 | dev_err(gpmc->dev, "failed to probe DT children\n"); |
| 2202 | gpmc_free_irq(gpmc); | 2288 | goto dt_children_failed; |
| 2203 | goto fail; | ||
| 2204 | } | 2289 | } |
| 2205 | 2290 | ||
| 2206 | return 0; | 2291 | return 0; |
| 2207 | 2292 | ||
| 2208 | fail: | 2293 | dt_children_failed: |
| 2294 | gpmc_free_irq(gpmc); | ||
| 2295 | setup_irq_failed: | ||
| 2296 | gpmc_gpio_exit(gpmc); | ||
| 2297 | gpio_init_failed: | ||
| 2298 | gpmc_mem_exit(); | ||
| 2209 | pm_runtime_put_sync(&pdev->dev); | 2299 | pm_runtime_put_sync(&pdev->dev); |
| 2300 | pm_runtime_disable(&pdev->dev); | ||
| 2301 | |||
| 2210 | return rc; | 2302 | return rc; |
| 2211 | } | 2303 | } |
| 2212 | 2304 | ||
| @@ -2215,6 +2307,7 @@ static int gpmc_remove(struct platform_device *pdev) | |||
| 2215 | struct gpmc_device *gpmc = platform_get_drvdata(pdev); | 2307 | struct gpmc_device *gpmc = platform_get_drvdata(pdev); |
| 2216 | 2308 | ||
| 2217 | gpmc_free_irq(gpmc); | 2309 | gpmc_free_irq(gpmc); |
| 2310 | gpmc_gpio_exit(gpmc); | ||
| 2218 | gpmc_mem_exit(); | 2311 | gpmc_mem_exit(); |
| 2219 | pm_runtime_put_sync(&pdev->dev); | 2312 | pm_runtime_put_sync(&pdev->dev); |
| 2220 | pm_runtime_disable(&pdev->dev); | 2313 | pm_runtime_disable(&pdev->dev); |
