Loading drivers/pinctrl/pinctrl-bm1880.c +287 −3 Original line number Diff line number Diff line Loading @@ -4,8 +4,6 @@ * * Copyright (c) 2019 Linaro Ltd. * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> * * TODO: Drive strength support */ #include <linux/io.h> Loading @@ -29,6 +27,7 @@ * @ngroups: Number of @groups * @funcs: Pinmux functions * @nfuncs: Number of @funcs * @pconf: Pinconf data */ struct bm1880_pinctrl { void __iomem *base; Loading @@ -37,6 +36,7 @@ struct bm1880_pinctrl { unsigned int ngroups; const struct bm1880_pinmux_function *funcs; unsigned int nfuncs; const struct bm1880_pinconf_data *pinconf; }; /** Loading Loading @@ -69,6 +69,14 @@ struct bm1880_pinmux_function { u8 mux_shift; }; /** * struct bm1880_pinconf_data - pinconf data * @drv_bits: Drive strength bit width */ struct bm1880_pinconf_data { u32 drv_bits; }; static const struct pinctrl_pin_desc bm1880_pins[] = { PINCTRL_PIN(0, "MIO0"), PINCTRL_PIN(1, "MIO1"), Loading Loading @@ -785,6 +793,126 @@ static const struct bm1880_pinmux_function bm1880_pmux_functions[] = { BM1880_PINMUX_FUNCTION(spi0, 1), }; #define BM1880_PINCONF_DAT(_width) \ { \ .drv_bits = _width, \ } static const struct bm1880_pinconf_data bm1880_pinconf[] = { BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), }; static int bm1880_pctrl_get_groups_count(struct pinctrl_dev *pctldev) { struct bm1880_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); Loading Loading @@ -878,9 +1006,145 @@ static int bm1880_pinmux_set_mux(struct pinctrl_dev *pctldev, #define BM1880_PINCONF_PULLCTRL(pin) BM1880_PINCONF(pin, 0) #define BM1880_PINCONF_PULLUP(pin) BM1880_PINCONF(pin, 1) #define BM1880_PINCONF_PULLDOWN(pin) BM1880_PINCONF(pin, 2) #define BM1880_PINCONF_DRV(pin) BM1880_PINCONF(pin, 6) #define BM1880_PINCONF_SCHMITT(pin) BM1880_PINCONF(pin, 9) #define BM1880_PINCONF_SLEW(pin) BM1880_PINCONF(pin, 10) static int bm1880_pinconf_drv_set(unsigned int mA, u32 width, u32 *regval, u32 bit_offset) { u32 _regval; _regval = *regval; /* * There are two sets of drive strength bit width exposed by the * SoC at 4mA step, hence we need to handle them separately. */ if (width == 0x03) { switch (mA) { case 4: _regval &= ~(width << bit_offset); _regval |= (0 << bit_offset); break; case 8: _regval &= ~(width << bit_offset); _regval |= (1 << bit_offset); break; case 12: _regval &= ~(width << bit_offset); _regval |= (2 << bit_offset); break; case 16: _regval &= ~(width << bit_offset); _regval |= (3 << bit_offset); break; case 20: _regval &= ~(width << bit_offset); _regval |= (4 << bit_offset); break; case 24: _regval &= ~(width << bit_offset); _regval |= (5 << bit_offset); break; case 28: _regval &= ~(width << bit_offset); _regval |= (6 << bit_offset); break; case 32: _regval &= ~(width << bit_offset); _regval |= (7 << bit_offset); break; default: return -EINVAL; } } else { switch (mA) { case 4: _regval &= ~(width << bit_offset); _regval |= (0 << bit_offset); break; case 8: _regval &= ~(width << bit_offset); _regval |= (1 << bit_offset); break; case 12: _regval &= ~(width << bit_offset); _regval |= (2 << bit_offset); break; case 16: _regval &= ~(width << bit_offset); _regval |= (3 << bit_offset); break; default: return -EINVAL; } } *regval = _regval; return 0; } static int bm1880_pinconf_drv_get(u32 width, u32 drv) { int ret = -ENOTSUPP; /* * There are two sets of drive strength bit width exposed by the * SoC at 4mA step, hence we need to handle them separately. */ if (width == 0x03) { switch (drv) { case 0: ret = 4; break; case 1: ret = 8; break; case 2: ret = 12; break; case 3: ret = 16; break; case 4: ret = 20; break; case 5: ret = 24; break; case 6: ret = 28; break; case 7: ret = 32; break; default: break; } } else { switch (drv) { case 0: ret = 4; break; case 1: ret = 8; break; case 2: ret = 12; break; case 3: ret = 16; break; default: break; } } return ret; } static int bm1880_pinconf_cfg_get(struct pinctrl_dev *pctldev, unsigned int pin, unsigned long *config) Loading @@ -889,6 +1153,7 @@ static int bm1880_pinconf_cfg_get(struct pinctrl_dev *pctldev, unsigned int param = pinconf_to_config_param(*config); unsigned int arg = 0; u32 regval, offset, bit_offset; int ret; offset = (pin >> 1) << 2; regval = readl_relaxed(pctrl->base + BM1880_REG_MUX + offset); Loading @@ -914,6 +1179,15 @@ static int bm1880_pinconf_cfg_get(struct pinctrl_dev *pctldev, bit_offset = BM1880_PINCONF_SLEW(pin); arg = !!(regval & BIT(bit_offset)); break; case PIN_CONFIG_DRIVE_STRENGTH: bit_offset = BM1880_PINCONF_DRV(pin); ret = bm1880_pinconf_drv_get(pctrl->pinconf[pin].drv_bits, !!(regval & BIT(bit_offset))); if (ret < 0) return ret; arg = ret; break; default: return -ENOTSUPP; } Loading @@ -930,7 +1204,7 @@ static int bm1880_pinconf_cfg_set(struct pinctrl_dev *pctldev, { struct bm1880_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); u32 regval, offset, bit_offset; int i; int i, ret; offset = (pin >> 1) << 2; regval = readl_relaxed(pctrl->base + BM1880_REG_MUX + offset); Loading Loading @@ -966,6 +1240,15 @@ static int bm1880_pinconf_cfg_set(struct pinctrl_dev *pctldev, else regval &= ~BIT(bit_offset); break; case PIN_CONFIG_DRIVE_STRENGTH: bit_offset = BM1880_PINCONF_DRV(pin); ret = bm1880_pinconf_drv_set(arg, pctrl->pinconf[pin].drv_bits, ®val, bit_offset); if (ret < 0) return ret; break; default: dev_warn(pctldev->dev, "unsupported configuration parameter '%u'\n", Loading Loading @@ -1041,6 +1324,7 @@ static int bm1880_pinctrl_probe(struct platform_device *pdev) pctrl->ngroups = ARRAY_SIZE(bm1880_pctrl_groups); pctrl->funcs = bm1880_pmux_functions; pctrl->nfuncs = ARRAY_SIZE(bm1880_pmux_functions); pctrl->pinconf = bm1880_pinconf; pctrl->pctrldev = devm_pinctrl_register(&pdev->dev, &bm1880_desc, pctrl); Loading Loading
drivers/pinctrl/pinctrl-bm1880.c +287 −3 Original line number Diff line number Diff line Loading @@ -4,8 +4,6 @@ * * Copyright (c) 2019 Linaro Ltd. * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org> * * TODO: Drive strength support */ #include <linux/io.h> Loading @@ -29,6 +27,7 @@ * @ngroups: Number of @groups * @funcs: Pinmux functions * @nfuncs: Number of @funcs * @pconf: Pinconf data */ struct bm1880_pinctrl { void __iomem *base; Loading @@ -37,6 +36,7 @@ struct bm1880_pinctrl { unsigned int ngroups; const struct bm1880_pinmux_function *funcs; unsigned int nfuncs; const struct bm1880_pinconf_data *pinconf; }; /** Loading Loading @@ -69,6 +69,14 @@ struct bm1880_pinmux_function { u8 mux_shift; }; /** * struct bm1880_pinconf_data - pinconf data * @drv_bits: Drive strength bit width */ struct bm1880_pinconf_data { u32 drv_bits; }; static const struct pinctrl_pin_desc bm1880_pins[] = { PINCTRL_PIN(0, "MIO0"), PINCTRL_PIN(1, "MIO1"), Loading Loading @@ -785,6 +793,126 @@ static const struct bm1880_pinmux_function bm1880_pmux_functions[] = { BM1880_PINMUX_FUNCTION(spi0, 1), }; #define BM1880_PINCONF_DAT(_width) \ { \ .drv_bits = _width, \ } static const struct bm1880_pinconf_data bm1880_pinconf[] = { BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x03), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), BM1880_PINCONF_DAT(0x02), }; static int bm1880_pctrl_get_groups_count(struct pinctrl_dev *pctldev) { struct bm1880_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); Loading Loading @@ -878,9 +1006,145 @@ static int bm1880_pinmux_set_mux(struct pinctrl_dev *pctldev, #define BM1880_PINCONF_PULLCTRL(pin) BM1880_PINCONF(pin, 0) #define BM1880_PINCONF_PULLUP(pin) BM1880_PINCONF(pin, 1) #define BM1880_PINCONF_PULLDOWN(pin) BM1880_PINCONF(pin, 2) #define BM1880_PINCONF_DRV(pin) BM1880_PINCONF(pin, 6) #define BM1880_PINCONF_SCHMITT(pin) BM1880_PINCONF(pin, 9) #define BM1880_PINCONF_SLEW(pin) BM1880_PINCONF(pin, 10) static int bm1880_pinconf_drv_set(unsigned int mA, u32 width, u32 *regval, u32 bit_offset) { u32 _regval; _regval = *regval; /* * There are two sets of drive strength bit width exposed by the * SoC at 4mA step, hence we need to handle them separately. */ if (width == 0x03) { switch (mA) { case 4: _regval &= ~(width << bit_offset); _regval |= (0 << bit_offset); break; case 8: _regval &= ~(width << bit_offset); _regval |= (1 << bit_offset); break; case 12: _regval &= ~(width << bit_offset); _regval |= (2 << bit_offset); break; case 16: _regval &= ~(width << bit_offset); _regval |= (3 << bit_offset); break; case 20: _regval &= ~(width << bit_offset); _regval |= (4 << bit_offset); break; case 24: _regval &= ~(width << bit_offset); _regval |= (5 << bit_offset); break; case 28: _regval &= ~(width << bit_offset); _regval |= (6 << bit_offset); break; case 32: _regval &= ~(width << bit_offset); _regval |= (7 << bit_offset); break; default: return -EINVAL; } } else { switch (mA) { case 4: _regval &= ~(width << bit_offset); _regval |= (0 << bit_offset); break; case 8: _regval &= ~(width << bit_offset); _regval |= (1 << bit_offset); break; case 12: _regval &= ~(width << bit_offset); _regval |= (2 << bit_offset); break; case 16: _regval &= ~(width << bit_offset); _regval |= (3 << bit_offset); break; default: return -EINVAL; } } *regval = _regval; return 0; } static int bm1880_pinconf_drv_get(u32 width, u32 drv) { int ret = -ENOTSUPP; /* * There are two sets of drive strength bit width exposed by the * SoC at 4mA step, hence we need to handle them separately. */ if (width == 0x03) { switch (drv) { case 0: ret = 4; break; case 1: ret = 8; break; case 2: ret = 12; break; case 3: ret = 16; break; case 4: ret = 20; break; case 5: ret = 24; break; case 6: ret = 28; break; case 7: ret = 32; break; default: break; } } else { switch (drv) { case 0: ret = 4; break; case 1: ret = 8; break; case 2: ret = 12; break; case 3: ret = 16; break; default: break; } } return ret; } static int bm1880_pinconf_cfg_get(struct pinctrl_dev *pctldev, unsigned int pin, unsigned long *config) Loading @@ -889,6 +1153,7 @@ static int bm1880_pinconf_cfg_get(struct pinctrl_dev *pctldev, unsigned int param = pinconf_to_config_param(*config); unsigned int arg = 0; u32 regval, offset, bit_offset; int ret; offset = (pin >> 1) << 2; regval = readl_relaxed(pctrl->base + BM1880_REG_MUX + offset); Loading @@ -914,6 +1179,15 @@ static int bm1880_pinconf_cfg_get(struct pinctrl_dev *pctldev, bit_offset = BM1880_PINCONF_SLEW(pin); arg = !!(regval & BIT(bit_offset)); break; case PIN_CONFIG_DRIVE_STRENGTH: bit_offset = BM1880_PINCONF_DRV(pin); ret = bm1880_pinconf_drv_get(pctrl->pinconf[pin].drv_bits, !!(regval & BIT(bit_offset))); if (ret < 0) return ret; arg = ret; break; default: return -ENOTSUPP; } Loading @@ -930,7 +1204,7 @@ static int bm1880_pinconf_cfg_set(struct pinctrl_dev *pctldev, { struct bm1880_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev); u32 regval, offset, bit_offset; int i; int i, ret; offset = (pin >> 1) << 2; regval = readl_relaxed(pctrl->base + BM1880_REG_MUX + offset); Loading Loading @@ -966,6 +1240,15 @@ static int bm1880_pinconf_cfg_set(struct pinctrl_dev *pctldev, else regval &= ~BIT(bit_offset); break; case PIN_CONFIG_DRIVE_STRENGTH: bit_offset = BM1880_PINCONF_DRV(pin); ret = bm1880_pinconf_drv_set(arg, pctrl->pinconf[pin].drv_bits, ®val, bit_offset); if (ret < 0) return ret; break; default: dev_warn(pctldev->dev, "unsupported configuration parameter '%u'\n", Loading Loading @@ -1041,6 +1324,7 @@ static int bm1880_pinctrl_probe(struct platform_device *pdev) pctrl->ngroups = ARRAY_SIZE(bm1880_pctrl_groups); pctrl->funcs = bm1880_pmux_functions; pctrl->nfuncs = ARRAY_SIZE(bm1880_pmux_functions); pctrl->pinconf = bm1880_pinconf; pctrl->pctrldev = devm_pinctrl_register(&pdev->dev, &bm1880_desc, pctrl); Loading