Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

gpio: ixp4xx: Handle clock output on pin 14 and 15

This makes it possible to provide basic clock output on pins
14 and 15. The clocks are typically used by random electronics,
not modeled in the device tree, so they just need to be provided
on request.

In order to not disturb old systems that require that the
hardware defaults are kept in the clock setting bits, we only
manipulate these if either device tree property is present.
Once we know a device needs one of the clocks we can set it
in the device tree.

Reviewed-by: Andy Shevchenko <andy@kernel.org>
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>

authored by

Linus Walleij and committed by
Bartosz Golaszewski
9a9429b9 58bfaaac

+50 -1
+50 -1
drivers/gpio/gpio-ixp4xx.c
··· 38 38 #define IXP4XX_GPIO_STYLE_MASK GENMASK(2, 0) 39 39 #define IXP4XX_GPIO_STYLE_SIZE 3 40 40 41 + /* 42 + * Clock output control register defines. 43 + */ 44 + #define IXP4XX_GPCLK_CLK0DC_SHIFT 0 45 + #define IXP4XX_GPCLK_CLK0TC_SHIFT 4 46 + #define IXP4XX_GPCLK_CLK0_MASK GENMASK(7, 0) 47 + #define IXP4XX_GPCLK_MUX14 BIT(8) 48 + #define IXP4XX_GPCLK_CLK1DC_SHIFT 16 49 + #define IXP4XX_GPCLK_CLK1TC_SHIFT 20 50 + #define IXP4XX_GPCLK_CLK1_MASK GENMASK(23, 16) 51 + #define IXP4XX_GPCLK_MUX15 BIT(24) 52 + 41 53 /** 42 54 * struct ixp4xx_gpio - IXP4 GPIO state container 43 55 * @dev: containing device for this instance ··· 214 202 struct ixp4xx_gpio *g; 215 203 struct gpio_irq_chip *girq; 216 204 struct device_node *irq_parent; 205 + bool clk_14, clk_15; 206 + u32 val; 217 207 int ret; 218 208 219 209 g = devm_kzalloc(dev, sizeof(*g), GFP_KERNEL); ··· 240 226 g->fwnode = of_node_to_fwnode(np); 241 227 242 228 /* 229 + * If either clock output is enabled explicitly in the device tree 230 + * we take full control of the clock by masking off all bits for 231 + * the clock control and selectively enabling them. Otherwise 232 + * we leave the hardware default settings. 233 + * 234 + * Enable clock outputs with default timings of requested clock. 235 + * If you need control over TC and DC, add these to the device 236 + * tree bindings and use them here. 237 + */ 238 + clk_14 = of_property_read_bool(np, "intel,ixp4xx-gpio14-clkout"); 239 + clk_15 = of_property_read_bool(np, "intel,ixp4xx-gpio15-clkout"); 240 + 241 + /* 243 242 * Make sure GPIO 14 and 15 are NOT used as clocks but GPIO on 244 243 * specific machines. 245 244 */ 246 245 if (of_machine_is_compatible("dlink,dsm-g600-a") || 247 246 of_machine_is_compatible("iom,nas-100d")) 248 - __raw_writel(0x0, g->base + IXP4XX_REG_GPCLK); 247 + val = 0; 248 + else { 249 + val = __raw_readl(g->base + IXP4XX_REG_GPCLK); 250 + 251 + if (clk_14 || clk_15) { 252 + val &= ~(IXP4XX_GPCLK_MUX14 | IXP4XX_GPCLK_MUX15); 253 + val &= ~IXP4XX_GPCLK_CLK0_MASK; 254 + val &= ~IXP4XX_GPCLK_CLK1_MASK; 255 + if (clk_14) { 256 + /* IXP4XX_GPCLK_CLK0DC implicit low */ 257 + val |= (1 << IXP4XX_GPCLK_CLK0TC_SHIFT); 258 + val |= IXP4XX_GPCLK_MUX14; 259 + } 260 + 261 + if (clk_15) { 262 + /* IXP4XX_GPCLK_CLK1DC implicit low */ 263 + val |= (1 << IXP4XX_GPCLK_CLK1TC_SHIFT); 264 + val |= IXP4XX_GPCLK_MUX15; 265 + } 266 + } 267 + } 268 + 269 + __raw_writel(val, g->base + IXP4XX_REG_GPCLK); 249 270 250 271 /* 251 272 * This is a very special big-endian ARM issue: when the IXP4xx is