From 0ed8f1e5f4c4acf0ca9ec158c503cd1cc5e9dfec Mon Sep 17 00:00:00 2001 From: David Wu Date: Tue, 26 Nov 2019 09:39:49 +0800 Subject: net: gmac_rockchip: Add support for rk3308 Add the glue code to allow the rk3308 variant of the Rockchip gmac to provide network functionality. Signed-off-by: David Wu Reviewed-by: Kever Yang --- drivers/net/gmac_rockchip.c | 65 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) (limited to 'drivers') diff --git a/drivers/net/gmac_rockchip.c b/drivers/net/gmac_rockchip.c index d2c52b4c46..e152faf083 100644 --- a/drivers/net/gmac_rockchip.c +++ b/drivers/net/gmac_rockchip.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -173,6 +174,47 @@ static int rk3288_gmac_fix_mac_speed(struct dw_eth_dev *priv) return 0; } +static int rk3308_gmac_fix_mac_speed(struct dw_eth_dev *priv) +{ + struct rk3308_grf *grf; + struct clk clk_speed; + int speed, ret; + enum { + RK3308_GMAC_SPEED_SHIFT = 0x0, + RK3308_GMAC_SPEED_MASK = BIT(0), + RK3308_GMAC_SPEED_10M = 0, + RK3308_GMAC_SPEED_100M = BIT(0), + }; + + ret = clk_get_by_name(priv->phydev->dev, "clk_mac_speed", + &clk_speed); + if (ret) + return ret; + + switch (priv->phydev->speed) { + case 10: + speed = RK3308_GMAC_SPEED_10M; + ret = clk_set_rate(&clk_speed, 2500000); + if (ret) + return ret; + break; + case 100: + speed = RK3308_GMAC_SPEED_100M; + ret = clk_set_rate(&clk_speed, 25000000); + if (ret) + return ret; + break; + default: + debug("Unknown phy speed: %d\n", priv->phydev->speed); + return -EINVAL; + } + + grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + rk_clrsetreg(&grf->mac_con0, RK3308_GMAC_SPEED_MASK, speed); + + return 0; +} + static int rk3328_gmac_fix_mac_speed(struct dw_eth_dev *priv) { struct rk3328_grf_regs *grf; @@ -377,6 +419,22 @@ static void rk3288_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata) pdata->tx_delay << RK3288_CLK_TX_DL_CFG_GMAC_SHIFT); } +static void rk3308_gmac_set_to_rmii(struct gmac_rockchip_platdata *pdata) +{ + struct rk3308_grf *grf; + enum { + RK3308_GMAC_PHY_INTF_SEL_SHIFT = 2, + RK3308_GMAC_PHY_INTF_SEL_MASK = GENMASK(4, 2), + RK3308_GMAC_PHY_INTF_SEL_RMII = BIT(4), + }; + + grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF); + + rk_clrsetreg(&grf->mac_con0, + RK3308_GMAC_PHY_INTF_SEL_MASK, + RK3308_GMAC_PHY_INTF_SEL_RMII); +} + static void rk3328_gmac_set_to_rgmii(struct gmac_rockchip_platdata *pdata) { struct rk3328_grf_regs *grf; @@ -646,6 +704,11 @@ const struct rk_gmac_ops rk3288_gmac_ops = { .set_to_rgmii = rk3288_gmac_set_to_rgmii, }; +const struct rk_gmac_ops rk3308_gmac_ops = { + .fix_mac_speed = rk3308_gmac_fix_mac_speed, + .set_to_rmii = rk3308_gmac_set_to_rmii, +}; + const struct rk_gmac_ops rk3328_gmac_ops = { .fix_mac_speed = rk3328_gmac_fix_mac_speed, .set_to_rgmii = rk3328_gmac_set_to_rgmii, @@ -673,6 +736,8 @@ static const struct udevice_id rockchip_gmac_ids[] = { .data = (ulong)&rk3228_gmac_ops }, { .compatible = "rockchip,rk3288-gmac", .data = (ulong)&rk3288_gmac_ops }, + { .compatible = "rockchip,rk3308-mac", + .data = (ulong)&rk3308_gmac_ops }, { .compatible = "rockchip,rk3328-gmac", .data = (ulong)&rk3328_gmac_ops }, { .compatible = "rockchip,rk3368-gmac", -- cgit From 4ee6d51c5ada760f82eb3d771bc2909130984e98 Mon Sep 17 00:00:00 2001 From: David Wu Date: Tue, 3 Dec 2019 17:49:53 +0800 Subject: pwm: rk_pwm: Make PWM driver to support all Rockchip Socs This PWM driver can be used to support pwm functions for on all Rockchip Socs. The previous chips than RK3288 did not support polarity, and register layout was different from the RK3288 PWM. The RK3288 keep the current functions. RK3328 and the chips after it, which can support hardware lock, configure duty, period and polarity at next same period, to prevent the intermediate temporary state. Signed-off-by: David Wu Reviewed-by: Kever Yang --- drivers/pwm/rk_pwm.c | 138 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 119 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/pwm/rk_pwm.c b/drivers/pwm/rk_pwm.c index 88db294cf1..46888e9077 100644 --- a/drivers/pwm/rk_pwm.c +++ b/drivers/pwm/rk_pwm.c @@ -15,22 +15,38 @@ #include #include +DECLARE_GLOBAL_DATA_PTR; + +struct rockchip_pwm_data { + struct rockchip_pwm_regs regs; + unsigned int prescaler; + bool supports_polarity; + bool supports_lock; + u32 enable_conf; + u32 enable_conf_mask; +}; + struct rk_pwm_priv { - struct rk3288_pwm *regs; + fdt_addr_t base; ulong freq; - uint enable_conf; + u32 conf_polarity; + const struct rockchip_pwm_data *data; }; static int rk_pwm_set_invert(struct udevice *dev, uint channel, bool polarity) { struct rk_pwm_priv *priv = dev_get_priv(dev); + if (!priv->data->supports_polarity) { + debug("%s: Do not support polarity\n", __func__); + return 0; + } + debug("%s: polarity=%u\n", __func__, polarity); - priv->enable_conf &= ~(PWM_DUTY_MASK | PWM_INACTIVE_MASK); if (polarity) - priv->enable_conf |= PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSTIVE; + priv->conf_polarity = PWM_DUTY_NEGATIVE | PWM_INACTIVE_POSTIVE; else - priv->enable_conf |= PWM_DUTY_POSTIVE | PWM_INACTIVE_NEGATIVE; + priv->conf_polarity = PWM_DUTY_POSTIVE | PWM_INACTIVE_NEGATIVE; return 0; } @@ -39,20 +55,44 @@ static int rk_pwm_set_config(struct udevice *dev, uint channel, uint period_ns, uint duty_ns) { struct rk_pwm_priv *priv = dev_get_priv(dev); - struct rk3288_pwm *regs = priv->regs; + const struct rockchip_pwm_regs *regs = &priv->data->regs; unsigned long period, duty; + u32 ctrl; debug("%s: period_ns=%u, duty_ns=%u\n", __func__, period_ns, duty_ns); - writel(PWM_SEL_SRC_CLK | PWM_OUTPUT_LEFT | PWM_LP_DISABLE | - PWM_CONTINUOUS | priv->enable_conf | - RK_PWM_DISABLE, - ®s->ctrl); - period = lldiv((uint64_t)(priv->freq / 1000) * period_ns, 1000000); - duty = lldiv((uint64_t)(priv->freq / 1000) * duty_ns, 1000000); + ctrl = readl(priv->base + regs->ctrl); + /* + * Lock the period and duty of previous configuration, then + * change the duty and period, that would not be effective. + */ + if (priv->data->supports_lock) { + ctrl |= PWM_LOCK; + writel(ctrl, priv->base + regs->ctrl); + } + + period = lldiv((uint64_t)priv->freq * period_ns, + priv->data->prescaler * 1000000000); + duty = lldiv((uint64_t)priv->freq * duty_ns, + priv->data->prescaler * 1000000000); + + writel(period, priv->base + regs->period); + writel(duty, priv->base + regs->duty); + + if (priv->data->supports_polarity) { + ctrl &= ~(PWM_DUTY_MASK | PWM_INACTIVE_MASK); + ctrl |= priv->conf_polarity; + } + + /* + * Unlock and set polarity at the same time, + * the configuration of duty, period and polarity + * would be effective together at next period. + */ + if (priv->data->supports_lock) + ctrl &= ~PWM_LOCK; + writel(ctrl, priv->base + regs->ctrl); - writel(period, ®s->period_hpr); - writel(duty, ®s->duty_lpr); debug("%s: period=%lu, duty=%lu\n", __func__, period, duty); return 0; @@ -61,10 +101,20 @@ static int rk_pwm_set_config(struct udevice *dev, uint channel, uint period_ns, static int rk_pwm_set_enable(struct udevice *dev, uint channel, bool enable) { struct rk_pwm_priv *priv = dev_get_priv(dev); - struct rk3288_pwm *regs = priv->regs; + const struct rockchip_pwm_regs *regs = &priv->data->regs; + u32 ctrl; debug("%s: Enable '%s'\n", __func__, dev->name); - clrsetbits_le32(®s->ctrl, RK_PWM_ENABLE, enable ? RK_PWM_ENABLE : 0); + + ctrl = readl(priv->base + regs->ctrl); + ctrl &= ~priv->data->enable_conf_mask; + + if (enable) + ctrl |= priv->data->enable_conf; + else + ctrl &= ~priv->data->enable_conf; + + writel(ctrl, priv->base + regs->ctrl); return 0; } @@ -73,7 +123,7 @@ static int rk_pwm_ofdata_to_platdata(struct udevice *dev) { struct rk_pwm_priv *priv = dev_get_priv(dev); - priv->regs = (struct rk3288_pwm *)dev_read_addr(dev); + priv->base = dev_read_addr(dev); return 0; } @@ -89,8 +139,12 @@ static int rk_pwm_probe(struct udevice *dev) debug("%s get clock fail!\n", __func__); return -EINVAL; } + priv->freq = clk_get_rate(&clk); - priv->enable_conf = PWM_DUTY_POSTIVE | PWM_INACTIVE_POSTIVE; + priv->data = (struct rockchip_pwm_data *)dev_get_driver_data(dev); + + if (priv->data->supports_polarity) + priv->conf_polarity = PWM_DUTY_POSTIVE | PWM_INACTIVE_POSTIVE; return 0; } @@ -101,8 +155,54 @@ static const struct pwm_ops rk_pwm_ops = { .set_enable = rk_pwm_set_enable, }; +static const struct rockchip_pwm_data pwm_data_v1 = { + .regs = { + .duty = 0x04, + .period = 0x08, + .cntr = 0x00, + .ctrl = 0x0c, + }, + .prescaler = 2, + .supports_polarity = false, + .supports_lock = false, + .enable_conf = PWM_CTRL_OUTPUT_EN | PWM_CTRL_TIMER_EN, + .enable_conf_mask = BIT(1) | BIT(3), +}; + +static const struct rockchip_pwm_data pwm_data_v2 = { + .regs = { + .duty = 0x08, + .period = 0x04, + .cntr = 0x00, + .ctrl = 0x0c, + }, + .prescaler = 1, + .supports_polarity = true, + .supports_lock = false, + .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | RK_PWM_ENABLE | + PWM_CONTINUOUS, + .enable_conf_mask = GENMASK(2, 0) | BIT(5) | BIT(8), +}; + +static const struct rockchip_pwm_data pwm_data_v3 = { + .regs = { + .duty = 0x08, + .period = 0x04, + .cntr = 0x00, + .ctrl = 0x0c, + }, + .prescaler = 1, + .supports_polarity = true, + .supports_lock = true, + .enable_conf = PWM_OUTPUT_LEFT | PWM_LP_DISABLE | RK_PWM_ENABLE | + PWM_CONTINUOUS, + .enable_conf_mask = GENMASK(2, 0) | BIT(5) | BIT(8), +}; + static const struct udevice_id rk_pwm_ids[] = { - { .compatible = "rockchip,rk3288-pwm" }, + { .compatible = "rockchip,rk2928-pwm", .data = (ulong)&pwm_data_v1}, + { .compatible = "rockchip,rk3288-pwm", .data = (ulong)&pwm_data_v2}, + { .compatible = "rockchip,rk3328-pwm", .data = (ulong)&pwm_data_v3}, { } }; -- cgit From 41eee945ce2a9a2a0955d30ee03b5653fdd04cbc Mon Sep 17 00:00:00 2001 From: David Wu Date: Tue, 3 Dec 2019 19:26:50 +0800 Subject: pinctrl: rockchip: Add pinctrl support for rk3308 An iomux register contains 8 pins, each of which is represented by 2 bits, but the register offset is 0x8. For example, GRF_GPIO0A_IOMUX offset is 0x0, but GRF_GPIO0B_IOMUX offset is 0x8, the offset 0x4 is reserved. So add a type IOMUX_8WIDTH_2BIT to calculate offset. Signed-off-by: David Wu Reviewed-by: Kever Yang --- drivers/pinctrl/rockchip/Makefile | 1 + drivers/pinctrl/rockchip/pinctrl-rk3308.c | 464 +++++++++++++++++++++++ drivers/pinctrl/rockchip/pinctrl-rockchip-core.c | 3 +- drivers/pinctrl/rockchip/pinctrl-rockchip.h | 1 + 4 files changed, 468 insertions(+), 1 deletion(-) create mode 100644 drivers/pinctrl/rockchip/pinctrl-rk3308.c (limited to 'drivers') diff --git a/drivers/pinctrl/rockchip/Makefile b/drivers/pinctrl/rockchip/Makefile index 83913f668f..fcf19f877a 100644 --- a/drivers/pinctrl/rockchip/Makefile +++ b/drivers/pinctrl/rockchip/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_ROCKCHIP_RK3128) += pinctrl-rk3128.o obj-$(CONFIG_ROCKCHIP_RK3188) += pinctrl-rk3188.o obj-$(CONFIG_ROCKCHIP_RK322X) += pinctrl-rk322x.o obj-$(CONFIG_ROCKCHIP_RK3288) += pinctrl-rk3288.o +obj-$(CONFIG_ROCKCHIP_RK3308) += pinctrl-rk3308.o obj-$(CONFIG_ROCKCHIP_RK3328) += pinctrl-rk3328.o obj-$(CONFIG_ROCKCHIP_RK3368) += pinctrl-rk3368.o obj-$(CONFIG_ROCKCHIP_RK3399) += pinctrl-rk3399.o diff --git a/drivers/pinctrl/rockchip/pinctrl-rk3308.c b/drivers/pinctrl/rockchip/pinctrl-rk3308.c new file mode 100644 index 0000000000..abd57e54a5 --- /dev/null +++ b/drivers/pinctrl/rockchip/pinctrl-rk3308.c @@ -0,0 +1,464 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2019 Rockchip Electronics Co., Ltd + */ + +#include +#include +#include +#include +#include + +#include "pinctrl-rockchip.h" + +static struct rockchip_mux_recalced_data rk3308_mux_recalced_data[] = { + { + .num = 1, + .pin = 14, + .reg = 0x28, + .bit = 12, + .mask = 0xf + }, { + .num = 1, + .pin = 15, + .reg = 0x2c, + .bit = 0, + .mask = 0x3 + }, { + .num = 1, + .pin = 18, + .reg = 0x30, + .bit = 4, + .mask = 0xf + }, { + .num = 1, + .pin = 19, + .reg = 0x30, + .bit = 8, + .mask = 0xf + }, { + .num = 1, + .pin = 20, + .reg = 0x30, + .bit = 12, + .mask = 0xf + }, { + .num = 1, + .pin = 21, + .reg = 0x34, + .bit = 0, + .mask = 0xf + }, { + .num = 1, + .pin = 22, + .reg = 0x34, + .bit = 4, + .mask = 0xf + }, { + .num = 1, + .pin = 23, + .reg = 0x34, + .bit = 8, + .mask = 0xf + }, { + .num = 3, + .pin = 12, + .reg = 0x68, + .bit = 8, + .mask = 0xf + }, { + .num = 3, + .pin = 13, + .reg = 0x68, + .bit = 12, + .mask = 0xf + }, { + .num = 2, + .pin = 2, + .reg = 0x608, + .bit = 0, + .mask = 0x7 + }, { + .num = 2, + .pin = 3, + .reg = 0x608, + .bit = 4, + .mask = 0x7 + }, { + .num = 2, + .pin = 16, + .reg = 0x610, + .bit = 8, + .mask = 0x7 + }, { + .num = 3, + .pin = 10, + .reg = 0x610, + .bit = 0, + .mask = 0x7 + }, { + .num = 3, + .pin = 11, + .reg = 0x610, + .bit = 4, + .mask = 0x7 + }, +}; + +static struct rockchip_mux_route_data rk3308_mux_route_data[] = { + { + /* rtc_clk */ + .bank_num = 0, + .pin = 19, + .func = 1, + .route_offset = 0x314, + .route_val = BIT(16 + 0) | BIT(0), + }, { + /* uart2_rxm0 */ + .bank_num = 1, + .pin = 22, + .func = 2, + .route_offset = 0x314, + .route_val = BIT(16 + 2) | BIT(16 + 3), + }, { + /* uart2_rxm1 */ + .bank_num = 4, + .pin = 26, + .func = 2, + .route_offset = 0x314, + .route_val = BIT(16 + 2) | BIT(16 + 3) | BIT(2), + }, { + /* i2c3_sdam0 */ + .bank_num = 0, + .pin = 15, + .func = 2, + .route_offset = 0x608, + .route_val = BIT(16 + 8) | BIT(16 + 9), + }, { + /* i2c3_sdam1 */ + .bank_num = 3, + .pin = 12, + .func = 2, + .route_offset = 0x608, + .route_val = BIT(16 + 8) | BIT(16 + 9) | BIT(8), + }, { + /* i2c3_sdam2 */ + .bank_num = 2, + .pin = 0, + .func = 3, + .route_offset = 0x608, + .route_val = BIT(16 + 8) | BIT(16 + 9) | BIT(9), + }, { + /* i2s-8ch-1-sclktxm0 */ + .bank_num = 1, + .pin = 3, + .func = 2, + .route_offset = 0x308, + .route_val = BIT(16 + 3), + }, { + /* i2s-8ch-1-sclkrxm0 */ + .bank_num = 1, + .pin = 4, + .func = 2, + .route_offset = 0x308, + .route_val = BIT(16 + 3), + }, { + /* i2s-8ch-1-sclktxm1 */ + .bank_num = 1, + .pin = 13, + .func = 2, + .route_offset = 0x308, + .route_val = BIT(16 + 3) | BIT(3), + }, { + /* i2s-8ch-1-sclkrxm1 */ + .bank_num = 1, + .pin = 14, + .func = 2, + .route_offset = 0x308, + .route_val = BIT(16 + 3) | BIT(3), + }, { + /* pdm-clkm0 */ + .bank_num = 1, + .pin = 4, + .func = 3, + .route_offset = 0x308, + .route_val = BIT(16 + 12) | BIT(16 + 13), + }, { + /* pdm-clkm1 */ + .bank_num = 1, + .pin = 14, + .func = 4, + .route_offset = 0x308, + .route_val = BIT(16 + 12) | BIT(16 + 13) | BIT(12), + }, { + /* pdm-clkm2 */ + .bank_num = 2, + .pin = 6, + .func = 2, + .route_offset = 0x308, + .route_val = BIT(16 + 12) | BIT(16 + 13) | BIT(13), + }, { + /* pdm-clkm-m2 */ + .bank_num = 2, + .pin = 4, + .func = 3, + .route_offset = 0x600, + .route_val = BIT(16 + 2) | BIT(2), + }, { + /* spi1_miso */ + .bank_num = 3, + .pin = 10, + .func = 3, + .route_offset = 0x314, + .route_val = BIT(16 + 9), + }, { + /* spi1_miso_m1 */ + .bank_num = 2, + .pin = 4, + .func = 2, + .route_offset = 0x314, + .route_val = BIT(16 + 9) | BIT(9), + }, { + /* mac_rxd0_m0 */ + .bank_num = 1, + .pin = 20, + .func = 3, + .route_offset = 0x314, + .route_val = BIT(16 + 14), + }, { + /* mac_rxd0_m1 */ + .bank_num = 4, + .pin = 2, + .func = 2, + .route_offset = 0x314, + .route_val = BIT(16 + 14) | BIT(14), + }, { + /* uart3_rx */ + .bank_num = 3, + .pin = 12, + .func = 4, + .route_offset = 0x314, + .route_val = BIT(16 + 15), + }, { + /* uart3_rx_m1 */ + .bank_num = 0, + .pin = 17, + .func = 3, + .route_offset = 0x314, + .route_val = BIT(16 + 15) | BIT(15), + }, +}; + +static int rk3308_set_mux(struct rockchip_pin_bank *bank, int pin, int mux) +{ + struct rockchip_pinctrl_priv *priv = bank->priv; + int iomux_num = (pin / 8); + struct regmap *regmap; + int reg, ret, mask, mux_type; + u8 bit; + u32 data, route_reg, route_val; + + regmap = (bank->iomux[iomux_num].type & IOMUX_SOURCE_PMU) + ? priv->regmap_pmu : priv->regmap_base; + + /* get basic quadrupel of mux registers and the correct reg inside */ + mux_type = bank->iomux[iomux_num].type; + reg = bank->iomux[iomux_num].offset; + reg += rockchip_get_mux_data(mux_type, pin, &bit, &mask); + + if (bank->recalced_mask & BIT(pin)) + rockchip_get_recalced_mux(bank, pin, ®, &bit, &mask); + + if (bank->route_mask & BIT(pin)) { + if (rockchip_get_mux_route(bank, pin, mux, &route_reg, + &route_val)) { + ret = regmap_write(regmap, route_reg, route_val); + if (ret) + return ret; + } + } + + data = (mask << (bit + 16)); + data |= (mux & mask) << bit; + ret = regmap_write(regmap, reg, data); + + return ret; +} + +#define RK3308_PULL_OFFSET 0xa0 + +static void rk3308_calc_pull_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) +{ + struct rockchip_pinctrl_priv *priv = bank->priv; + + *regmap = priv->regmap_base; + *reg = RK3308_PULL_OFFSET; + *reg += bank->bank_num * ROCKCHIP_PULL_BANK_STRIDE; + *reg += ((pin_num / ROCKCHIP_PULL_PINS_PER_REG) * 4); + + *bit = (pin_num % ROCKCHIP_PULL_PINS_PER_REG); + *bit *= ROCKCHIP_PULL_BITS_PER_PIN; +} + +static int rk3308_set_pull(struct rockchip_pin_bank *bank, + int pin_num, int pull) +{ + struct regmap *regmap; + int reg, ret; + u8 bit, type; + u32 data; + + if (pull == PIN_CONFIG_BIAS_PULL_PIN_DEFAULT) + return -ENOTSUPP; + + rk3308_calc_pull_reg_and_bit(bank, pin_num, ®map, ®, &bit); + type = bank->pull_type[pin_num / 8]; + ret = rockchip_translate_pull_value(type, pull); + if (ret < 0) { + debug("unsupported pull setting %d\n", pull); + return ret; + } + + /* enable the write to the equivalent lower bits */ + data = ((1 << ROCKCHIP_PULL_BITS_PER_PIN) - 1) << (bit + 16); + data |= (ret << bit); + + ret = regmap_write(regmap, reg, data); + + return ret; +} + +#define RK3308_DRV_GRF_OFFSET 0x100 + +static void rk3308_calc_drv_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, struct regmap **regmap, + int *reg, u8 *bit) +{ + struct rockchip_pinctrl_priv *priv = bank->priv; + + *regmap = priv->regmap_base; + *reg = RK3308_DRV_GRF_OFFSET; + *reg += bank->bank_num * ROCKCHIP_DRV_BANK_STRIDE; + *reg += ((pin_num / ROCKCHIP_DRV_PINS_PER_REG) * 4); + + *bit = (pin_num % ROCKCHIP_DRV_PINS_PER_REG); + *bit *= ROCKCHIP_DRV_BITS_PER_PIN; +} + +static int rk3308_set_drive(struct rockchip_pin_bank *bank, + int pin_num, int strength) +{ + struct regmap *regmap; + int reg, ret; + u32 data; + u8 bit; + int type = bank->drv[pin_num / 8].drv_type; + + rk3308_calc_drv_reg_and_bit(bank, pin_num, ®map, ®, &bit); + ret = rockchip_translate_drive_value(type, strength); + if (ret < 0) { + debug("unsupported driver strength %d\n", strength); + return ret; + } + + /* enable the write to the equivalent lower bits */ + data = ((1 << ROCKCHIP_DRV_BITS_PER_PIN) - 1) << (bit + 16); + data |= (ret << bit); + ret = regmap_write(regmap, reg, data); + return ret; +} + +#define RK3308_SCHMITT_PINS_PER_REG 8 +#define RK3308_SCHMITT_BANK_STRIDE 16 +#define RK3308_SCHMITT_GRF_OFFSET 0x1a0 + +static int rk3308_calc_schmitt_reg_and_bit(struct rockchip_pin_bank *bank, + int pin_num, + struct regmap **regmap, + int *reg, u8 *bit) +{ + struct rockchip_pinctrl_priv *priv = bank->priv; + + *regmap = priv->regmap_base; + *reg = RK3308_SCHMITT_GRF_OFFSET; + + *reg += bank->bank_num * RK3308_SCHMITT_BANK_STRIDE; + *reg += ((pin_num / RK3308_SCHMITT_PINS_PER_REG) * 4); + *bit = pin_num % RK3308_SCHMITT_PINS_PER_REG; + + return 0; +} + +static int rk3308_set_schmitt(struct rockchip_pin_bank *bank, + int pin_num, int enable) +{ + struct regmap *regmap; + int reg; + u8 bit; + u32 data; + + rk3308_calc_schmitt_reg_and_bit(bank, pin_num, ®map, ®, &bit); + /* enable the write to the equivalent lower bits */ + data = BIT(bit + 16) | (enable << bit); + + return regmap_write(regmap, reg, data); +} + +static struct rockchip_pin_bank rk3308_pin_banks[] = { + PIN_BANK_IOMUX_FLAGS(0, 32, "gpio0", IOMUX_8WIDTH_2BIT, + IOMUX_8WIDTH_2BIT, + IOMUX_8WIDTH_2BIT, + IOMUX_8WIDTH_2BIT), + PIN_BANK_IOMUX_FLAGS(1, 32, "gpio1", IOMUX_8WIDTH_2BIT, + IOMUX_8WIDTH_2BIT, + IOMUX_8WIDTH_2BIT, + IOMUX_8WIDTH_2BIT), + PIN_BANK_IOMUX_FLAGS(2, 32, "gpio2", IOMUX_8WIDTH_2BIT, + IOMUX_8WIDTH_2BIT, + IOMUX_8WIDTH_2BIT, + IOMUX_8WIDTH_2BIT), + PIN_BANK_IOMUX_FLAGS(3, 32, "gpio3", IOMUX_8WIDTH_2BIT, + IOMUX_8WIDTH_2BIT, + IOMUX_8WIDTH_2BIT, + IOMUX_8WIDTH_2BIT), + PIN_BANK_IOMUX_FLAGS(4, 32, "gpio4", IOMUX_8WIDTH_2BIT, + IOMUX_8WIDTH_2BIT, + IOMUX_8WIDTH_2BIT, + IOMUX_8WIDTH_2BIT), +}; + +static struct rockchip_pin_ctrl rk3308_pin_ctrl = { + .pin_banks = rk3308_pin_banks, + .nr_banks = ARRAY_SIZE(rk3308_pin_banks), + .grf_mux_offset = 0x0, + .iomux_recalced = rk3308_mux_recalced_data, + .niomux_recalced = ARRAY_SIZE(rk3308_mux_recalced_data), + .iomux_routes = rk3308_mux_route_data, + .niomux_routes = ARRAY_SIZE(rk3308_mux_route_data), + .set_mux = rk3308_set_mux, + .set_drive = rk3308_set_drive, + .set_pull = rk3308_set_pull, + .set_schmitt = rk3308_set_schmitt, +}; + +static const struct udevice_id rk3308_pinctrl_ids[] = { + { + .compatible = "rockchip,rk3308-pinctrl", + .data = (ulong)&rk3308_pin_ctrl + }, + { } +}; + +U_BOOT_DRIVER(pinctrl_rk3308) = { + .name = "rockchip_rk3308_pinctrl", + .id = UCLASS_PINCTRL, + .of_match = rk3308_pinctrl_ids, + .priv_auto_alloc_size = sizeof(struct rockchip_pinctrl_priv), + .ops = &rockchip_pinctrl_ops, +#if !CONFIG_IS_ENABLED(OF_PLATDATA) + .bind = dm_scan_fdt_dev, +#endif + .probe = rockchip_pinctrl_probe, +}; diff --git a/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c b/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c index 80dc431d20..0fd0416b18 100644 --- a/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c +++ b/drivers/pinctrl/rockchip/pinctrl-rockchip-core.c @@ -539,7 +539,8 @@ static struct rockchip_pin_ctrl *rockchip_pinctrl_get_soc_data(struct udevice *d * 4bit iomux'es are spread over two registers. */ inc = (iom->type & (IOMUX_WIDTH_4BIT | - IOMUX_WIDTH_3BIT)) ? 8 : 4; + IOMUX_WIDTH_3BIT | + IOMUX_8WIDTH_2BIT)) ? 8 : 4; if (iom->type & IOMUX_SOURCE_PMU) pmu_offs += inc; else diff --git a/drivers/pinctrl/rockchip/pinctrl-rockchip.h b/drivers/pinctrl/rockchip/pinctrl-rockchip.h index 9651e9c7a6..5edc7cbd74 100644 --- a/drivers/pinctrl/rockchip/pinctrl-rockchip.h +++ b/drivers/pinctrl/rockchip/pinctrl-rockchip.h @@ -16,6 +16,7 @@ #define IOMUX_SOURCE_PMU BIT(2) #define IOMUX_UNROUTED BIT(3) #define IOMUX_WIDTH_3BIT BIT(4) +#define IOMUX_8WIDTH_2BIT BIT(5) /** * Defined some common pins constants -- cgit