|
14 | 14 | #include <linux/of.h>
|
15 | 15 | #include <linux/of_address.h>
|
16 | 16 | #include <linux/platform_device.h>
|
| 17 | +#include <linux/reset-controller.h> |
17 | 18 | #include <linux/slab.h>
|
18 | 19 | #include <linux/spinlock.h>
|
19 | 20 |
|
@@ -2055,16 +2056,18 @@ static const struct clock_config stm32mp1_clock_cfg[] = {
|
2055 | 2056 | _DIV(RCC_DBGCFGR, 0, 3, 0, ck_trace_div_table)),
|
2056 | 2057 | };
|
2057 | 2058 |
|
2058 |
| -struct stm32_clock_match_data { |
| 2059 | +struct stm32_rcc_match_data { |
2059 | 2060 | const struct clock_config *cfg;
|
2060 | 2061 | unsigned int num;
|
2061 | 2062 | unsigned int maxbinding;
|
| 2063 | + u32 clear_offset; |
2062 | 2064 | };
|
2063 | 2065 |
|
2064 |
| -static struct stm32_clock_match_data stm32mp1_data = { |
| 2066 | +static struct stm32_rcc_match_data stm32mp1_data = { |
2065 | 2067 | .cfg = stm32mp1_clock_cfg,
|
2066 | 2068 | .num = ARRAY_SIZE(stm32mp1_clock_cfg),
|
2067 | 2069 | .maxbinding = STM32MP1_LAST_CLK,
|
| 2070 | + .clear_offset = RCC_CLR, |
2068 | 2071 | };
|
2069 | 2072 |
|
2070 | 2073 | static const struct of_device_id stm32mp1_match_data[] = {
|
@@ -2100,23 +2103,122 @@ static int stm32_register_hw_clk(struct device *dev,
|
2100 | 2103 | return 0;
|
2101 | 2104 | }
|
2102 | 2105 |
|
2103 |
| -static int stm32_rcc_init(struct device *dev, void __iomem *base, |
2104 |
| - const struct of_device_id *match_data) |
| 2106 | +#define STM32_RESET_ID_MASK GENMASK(15, 0) |
| 2107 | + |
| 2108 | +struct stm32_reset_data { |
| 2109 | + /* reset lock */ |
| 2110 | + spinlock_t lock; |
| 2111 | + struct reset_controller_dev rcdev; |
| 2112 | + void __iomem *membase; |
| 2113 | + u32 clear_offset; |
| 2114 | +}; |
| 2115 | + |
| 2116 | +static inline struct stm32_reset_data * |
| 2117 | +to_stm32_reset_data(struct reset_controller_dev *rcdev) |
2105 | 2118 | {
|
2106 |
| - struct clk_hw_onecell_data *clk_data; |
2107 |
| - struct clk_hw **hws; |
2108 |
| - const struct of_device_id *match; |
2109 |
| - const struct stm32_clock_match_data *data; |
2110 |
| - int err, n, max_binding; |
| 2119 | + return container_of(rcdev, struct stm32_reset_data, rcdev); |
| 2120 | +} |
2111 | 2121 |
|
2112 |
| - match = of_match_node(match_data, dev_of_node(dev)); |
2113 |
| - if (!match) { |
2114 |
| - dev_err(dev, "match data not found\n"); |
2115 |
| - return -ENODEV; |
| 2122 | +static int stm32_reset_update(struct reset_controller_dev *rcdev, |
| 2123 | + unsigned long id, bool assert) |
| 2124 | +{ |
| 2125 | + struct stm32_reset_data *data = to_stm32_reset_data(rcdev); |
| 2126 | + int reg_width = sizeof(u32); |
| 2127 | + int bank = id / (reg_width * BITS_PER_BYTE); |
| 2128 | + int offset = id % (reg_width * BITS_PER_BYTE); |
| 2129 | + |
| 2130 | + if (data->clear_offset) { |
| 2131 | + void __iomem *addr; |
| 2132 | + |
| 2133 | + addr = data->membase + (bank * reg_width); |
| 2134 | + if (!assert) |
| 2135 | + addr += data->clear_offset; |
| 2136 | + |
| 2137 | + writel(BIT(offset), addr); |
| 2138 | + |
| 2139 | + } else { |
| 2140 | + unsigned long flags; |
| 2141 | + u32 reg; |
| 2142 | + |
| 2143 | + spin_lock_irqsave(&data->lock, flags); |
| 2144 | + |
| 2145 | + reg = readl(data->membase + (bank * reg_width)); |
| 2146 | + |
| 2147 | + if (assert) |
| 2148 | + reg |= BIT(offset); |
| 2149 | + else |
| 2150 | + reg &= ~BIT(offset); |
| 2151 | + |
| 2152 | + writel(reg, data->membase + (bank * reg_width)); |
| 2153 | + |
| 2154 | + spin_unlock_irqrestore(&data->lock, flags); |
2116 | 2155 | }
|
2117 | 2156 |
|
| 2157 | + return 0; |
| 2158 | +} |
| 2159 | + |
| 2160 | +static int stm32_reset_assert(struct reset_controller_dev *rcdev, |
| 2161 | + unsigned long id) |
| 2162 | +{ |
| 2163 | + return stm32_reset_update(rcdev, id, true); |
| 2164 | +} |
| 2165 | + |
| 2166 | +static int stm32_reset_deassert(struct reset_controller_dev *rcdev, |
| 2167 | + unsigned long id) |
| 2168 | +{ |
| 2169 | + return stm32_reset_update(rcdev, id, false); |
| 2170 | +} |
| 2171 | + |
| 2172 | +static int stm32_reset_status(struct reset_controller_dev *rcdev, |
| 2173 | + unsigned long id) |
| 2174 | +{ |
| 2175 | + struct stm32_reset_data *data = to_stm32_reset_data(rcdev); |
| 2176 | + int reg_width = sizeof(u32); |
| 2177 | + int bank = id / (reg_width * BITS_PER_BYTE); |
| 2178 | + int offset = id % (reg_width * BITS_PER_BYTE); |
| 2179 | + u32 reg; |
| 2180 | + |
| 2181 | + reg = readl(data->membase + (bank * reg_width)); |
| 2182 | + |
| 2183 | + return !!(reg & BIT(offset)); |
| 2184 | +} |
| 2185 | + |
| 2186 | +static const struct reset_control_ops stm32_reset_ops = { |
| 2187 | + .assert = stm32_reset_assert, |
| 2188 | + .deassert = stm32_reset_deassert, |
| 2189 | + .status = stm32_reset_status, |
| 2190 | +}; |
| 2191 | + |
| 2192 | +static int stm32_rcc_reset_init(struct device *dev, void __iomem *base, |
| 2193 | + const struct of_device_id *match) |
| 2194 | +{ |
| 2195 | + const struct stm32_rcc_match_data *data = match->data; |
| 2196 | + struct stm32_reset_data *reset_data = NULL; |
| 2197 | + |
2118 | 2198 | data = match->data;
|
2119 | 2199 |
|
| 2200 | + reset_data = kzalloc(sizeof(*reset_data), GFP_KERNEL); |
| 2201 | + if (!reset_data) |
| 2202 | + return -ENOMEM; |
| 2203 | + |
| 2204 | + reset_data->membase = base; |
| 2205 | + reset_data->rcdev.owner = THIS_MODULE; |
| 2206 | + reset_data->rcdev.ops = &stm32_reset_ops; |
| 2207 | + reset_data->rcdev.of_node = dev_of_node(dev); |
| 2208 | + reset_data->rcdev.nr_resets = STM32_RESET_ID_MASK; |
| 2209 | + reset_data->clear_offset = data->clear_offset; |
| 2210 | + |
| 2211 | + return reset_controller_register(&reset_data->rcdev); |
| 2212 | +} |
| 2213 | + |
| 2214 | +static int stm32_rcc_clock_init(struct device *dev, void __iomem *base, |
| 2215 | + const struct of_device_id *match) |
| 2216 | +{ |
| 2217 | + const struct stm32_rcc_match_data *data = match->data; |
| 2218 | + struct clk_hw_onecell_data *clk_data; |
| 2219 | + struct clk_hw **hws; |
| 2220 | + int err, n, max_binding; |
| 2221 | + |
2120 | 2222 | max_binding = data->maxbinding;
|
2121 | 2223 |
|
2122 | 2224 | clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, max_binding),
|
@@ -2145,6 +2247,35 @@ static int stm32_rcc_init(struct device *dev, void __iomem *base,
|
2145 | 2247 | return of_clk_add_hw_provider(dev_of_node(dev), of_clk_hw_onecell_get, clk_data);
|
2146 | 2248 | }
|
2147 | 2249 |
|
| 2250 | +static int stm32_rcc_init(struct device *dev, void __iomem *base, |
| 2251 | + const struct of_device_id *match_data) |
| 2252 | +{ |
| 2253 | + const struct of_device_id *match; |
| 2254 | + int err; |
| 2255 | + |
| 2256 | + match = of_match_node(match_data, dev_of_node(dev)); |
| 2257 | + if (!match) { |
| 2258 | + dev_err(dev, "match data not found\n"); |
| 2259 | + return -ENODEV; |
| 2260 | + } |
| 2261 | + |
| 2262 | + /* RCC Reset Configuration */ |
| 2263 | + err = stm32_rcc_reset_init(dev, base, match); |
| 2264 | + if (err) { |
| 2265 | + pr_err("stm32mp1 reset failed to initialize\n"); |
| 2266 | + return err; |
| 2267 | + } |
| 2268 | + |
| 2269 | + /* RCC Clock Configuration */ |
| 2270 | + err = stm32_rcc_clock_init(dev, base, match); |
| 2271 | + if (err) { |
| 2272 | + pr_err("stm32mp1 clock failed to initialize\n"); |
| 2273 | + return err; |
| 2274 | + } |
| 2275 | + |
| 2276 | + return 0; |
| 2277 | +} |
| 2278 | + |
2148 | 2279 | static int stm32mp1_rcc_init(struct device *dev)
|
2149 | 2280 | {
|
2150 | 2281 | void __iomem *base;
|
|
0 commit comments