From 44d8ae5b6903a796b9868fc2b546b75e5ced2bfd Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 6 Apr 2015 20:33:34 +0200 Subject: sunxi: Introduce a hidden SUNXI_GEN_SUNxI Kconfig bool sun6i and newer (derived) SoCs such as the sun8i-a23, sun8i-a33 and sun9i have a various things in common, like having separate ahb reset control registers, the SID living inside the pmic, custom pmic busses, new style watchdog, etc. This commit introduces a new hidden SUNXI_GEN_SUN6I Kconfig bool which can be used to check for these features avoiding the need for an ever growing list of "#if defined CONFIG_MACH_SUN?I" conditionals as we add support for more "new style" sunxi SoCs. Note that this commit changes the behavior of the gmac and hdmi code for sun8i and the upcoming sun9i devices. This does not matter as sun8i does not have gmac nor hdmi, and sun9i has new hardware-blocks for these so the old code will not work there. Also this is intentional as if a sun8i / sun9i variant which does use the old hwblocks shows up then the GEN_SUN6I code paths will be the right ones to use. For completeness this also adds a SUNXI_GEN_SUN4I bool for A10/A13/A20. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- drivers/mmc/sunxi_mmc.c | 3 +-- drivers/video/sunxi_display.c | 10 +++++----- 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index 22335452c5..1c234e2eda 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -151,8 +151,7 @@ static int mmc_clk_io_on(int sdc_no) /* config ahb clock */ setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_MMC(sdc_no)); -#if defined(CONFIG_MACH_SUN6I) || defined(CONFIG_MACH_SUN8I) || \ - defined(CONFIG_MACH_SUN9I) +#ifdef CONFIG_SUNXI_GEN_SUN6I /* unassert reset */ setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_RESET_OFFSET_MMC(sdc_no)); #endif diff --git a/drivers/video/sunxi_display.c b/drivers/video/sunxi_display.c index d2341b0e36..2ee105690f 100644 --- a/drivers/video/sunxi_display.c +++ b/drivers/video/sunxi_display.c @@ -84,7 +84,7 @@ static int sunxi_hdmi_hpd_detect(int hpd_delay) CCM_HDMI_CTRL_PLL3); /* Set ahb gating to pass */ -#ifdef CONFIG_MACH_SUN6I +#ifdef CONFIG_SUNXI_GEN_SUN6I setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI); #endif setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI); @@ -113,7 +113,7 @@ static void sunxi_hdmi_shutdown(void) clrbits_le32(&hdmi->ctrl, SUNXI_HDMI_CTRL_ENABLE); clrbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_GATE); clrbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_HDMI); -#ifdef CONFIG_MACH_SUN6I +#ifdef CONFIG_SUNXI_GEN_SUN6I clrbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_HDMI); #endif clock_set_pll3(0); @@ -404,7 +404,7 @@ static void sunxi_composer_init(void) sunxi_frontend_init(); -#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I +#ifdef CONFIG_SUNXI_GEN_SUN6I /* Reset off */ setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DE_BE0); #endif @@ -549,7 +549,7 @@ static void sunxi_lcdc_init(void) (struct sunxi_lcdc_reg *)SUNXI_LCD0_BASE; /* Reset off */ -#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I +#ifdef CONFIG_SUNXI_GEN_SUN6I setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_LCD0); #else setbits_le32(&ccm->lcd0_ch0_clk_cfg, CCM_LCD_CH0_CTRL_RST); @@ -942,7 +942,7 @@ static void sunxi_vga_enable(void) static void sunxi_drc_init(void) { -#if defined CONFIG_MACH_SUN6I || defined CONFIG_MACH_SUN8I +#ifdef CONFIG_SUNXI_GEN_SUN6I struct sunxi_ccm_reg * const ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; -- cgit v1.2.3 From 8c3dacff1409109e3697ed60df0e7c93d1309a93 Mon Sep 17 00:00:00 2001 From: Vishnu Patekar Date: Sun, 1 Mar 2015 23:47:48 +0530 Subject: sunxi: Add basic A33 basic support Enable full support for the A33 SoC including display, otg-usb, etc. Signed-off-by: Vishnu Patekar Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- drivers/usb/musb-new/musb_regs.h | 5 +++++ drivers/video/sunxi_display.c | 3 +++ 2 files changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/musb-new/musb_regs.h b/drivers/usb/musb-new/musb_regs.h index 27e4ed4ec6..90288c4694 100644 --- a/drivers/usb/musb-new/musb_regs.h +++ b/drivers/usb/musb-new/musb_regs.h @@ -458,8 +458,13 @@ static inline u8 musb_read_ulpi_buscontrol(void __iomem *mbase) static inline u8 musb_read_configdata(void __iomem *mbase) { +#ifdef CONFIG_MACH_SUN8I_A33 + /* allwinner saves a reg, and we need to hardcode this */ + return 0xde; +#else musb_writeb(mbase, MUSB_INDEX, 0); return musb_readb(mbase, 0x10 + MUSB_CONFIGDATA); +#endif } static inline u16 musb_read_hwvers(void __iomem *mbase) diff --git a/drivers/video/sunxi_display.c b/drivers/video/sunxi_display.c index 2ee105690f..1163ecf061 100644 --- a/drivers/video/sunxi_display.c +++ b/drivers/video/sunxi_display.c @@ -947,6 +947,9 @@ static void sunxi_drc_init(void) (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; /* On sun6i the drc must be clocked even when in pass-through mode */ +#ifdef CONFIG_MACH_SUN8I_A33 + setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_SAT); +#endif setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_DRC0); clock_set_de_mod_clock(&ccm->iep_drc0_clk_cfg, 300000000); #endif -- cgit v1.2.3 From 90641f82f1700553640103bf58017c303be4e604 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 22 Apr 2015 17:03:17 +0200 Subject: sunxi: mmc: Fix card-detect gpio handling to work with the driver-model The driver-model gpio functions may return another value then -1 as error, make the sunxi mmc code properly handle this. Signed-off-by: Hans de Goede Reviewed-by: Simon Glass Acked-by: Ian Campbell --- drivers/mmc/sunxi_mmc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c index 1c234e2eda..c4300f25fd 100644 --- a/drivers/mmc/sunxi_mmc.c +++ b/drivers/mmc/sunxi_mmc.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -37,7 +38,7 @@ static int sunxi_mmc_getcd_gpio(int sdc_no) case 2: return sunxi_name_to_gpio(CONFIG_MMC2_CD_PIN); case 3: return sunxi_name_to_gpio(CONFIG_MMC3_CD_PIN); } - return -1; + return -EINVAL; } static int mmc_resource_init(int sdc_no) @@ -72,7 +73,7 @@ static int mmc_resource_init(int sdc_no) mmchost->mmc_no = sdc_no; cd_pin = sunxi_mmc_getcd_gpio(sdc_no); - if (cd_pin != -1) { + if (cd_pin >= 0) { ret = gpio_request(cd_pin, "mmc_cd"); if (!ret) ret = gpio_direction_input(cd_pin); @@ -424,7 +425,7 @@ static int sunxi_mmc_getcd(struct mmc *mmc) int cd_pin; cd_pin = sunxi_mmc_getcd_gpio(mmchost->mmc_no); - if (cd_pin == -1) + if (cd_pin < 0) return 1; return !gpio_get_value(cd_pin); -- cgit v1.2.3 From 1572819c5fb4c7f8596c973555211b37847fdf5d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 22 Apr 2015 17:45:59 +0200 Subject: sunxi: display: Fix gpio handling to work with the driver-model The driver-model gpio functions may return another value then -1 as error, make the sunxi display code properly handle this. Signed-off-by: Hans de Goede Reviewed-by: Simon Glass Acked-by: Ian Campbell --- drivers/video/sunxi_display.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/video/sunxi_display.c b/drivers/video/sunxi_display.c index 1163ecf061..48dbdf5795 100644 --- a/drivers/video/sunxi_display.c +++ b/drivers/video/sunxi_display.c @@ -600,19 +600,19 @@ static void sunxi_lcdc_panel_enable(void) * white while the lcd inits. */ pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_EN); - if (pin != -1) { + if (pin >= 0) { gpio_request(pin, "lcd_backlight_enable"); gpio_direction_output(pin, 0); } pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_PWM); - if (pin != -1) { + if (pin >= 0) { gpio_request(pin, "lcd_backlight_pwm"); gpio_direction_output(pin, PWM_OFF); } reset_pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_RESET); - if (reset_pin != -1) { + if (reset_pin >= 0) { gpio_request(reset_pin, "lcd_reset"); gpio_direction_output(reset_pin, 0); /* Assert reset */ } @@ -620,12 +620,12 @@ static void sunxi_lcdc_panel_enable(void) /* Give the backlight some time to turn off and power up the panel. */ mdelay(40); pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_POWER); - if (pin != -1) { + if (pin >= 0) { gpio_request(pin, "lcd_power"); gpio_direction_output(pin, 1); } - if (reset_pin != -1) + if (reset_pin >= 0) gpio_direction_output(reset_pin, 1); /* De-assert reset */ } @@ -640,11 +640,11 @@ static void sunxi_lcdc_backlight_enable(void) mdelay(40); pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_EN); - if (pin != -1) + if (pin >= 0) gpio_direction_output(pin, 1); pin = sunxi_name_to_gpio(CONFIG_VIDEO_LCD_BL_PWM); - if (pin != -1) + if (pin >= 0) gpio_direction_output(pin, PWM_ON); } @@ -961,7 +961,7 @@ static void sunxi_vga_external_dac_enable(void) int pin; pin = sunxi_name_to_gpio(CONFIG_VIDEO_VGA_EXTERNAL_DAC_EN); - if (pin != -1) { + if (pin >= 0) { gpio_request(pin, "vga_enable"); gpio_direction_output(pin, 1); } -- cgit v1.2.3 From 07ce60f3cd21de20576e69ba10beabc905643500 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 18 Apr 2015 11:33:44 -0600 Subject: sunxi: gpio: Rename GPIOs to include a 'P' prefix By convention, sunxi GPIOs are named PA1, PA2 instead of A1, A2. Change the driver model GPIO driver for sunxi to use these names. Signed-off-by: Simon Glass Acked-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/gpio/sunxi_gpio.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c index cf5c62463e..29301c43d0 100644 --- a/drivers/gpio/sunxi_gpio.c +++ b/drivers/gpio/sunxi_gpio.c @@ -249,10 +249,11 @@ static char *gpio_bank_name(int bank) { char *name; - name = malloc(2); + name = malloc(3); if (name) { - name[0] = 'A' + bank; - name[1] = '\0'; + name[0] = 'P'; + name[1] = 'A' + bank; + name[2] = '\0'; } return name; -- cgit v1.2.3 From a5ab8838c6b096ba6e4ba57fdb169cb8ecfea295 Mon Sep 17 00:00:00 2001 From: Simon Glass Date: Sat, 18 Apr 2015 11:33:43 -0600 Subject: sunxi: gpio: Add temporary implementation of name_to_gpio() Until sunxi moves to device tree (e.g. for USB) we need to convert named GPIOs to numbers. Add a function to do this. This fixes the USB / EHCI support not working on the LinkSprite pcDuino3 (which uses devicemodel). Signed-off-by: Simon Glass Acked-by: Hans de Goede Signed-off-by: Hans de Goede --- drivers/gpio/sunxi_gpio.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c index 29301c43d0..89209dfa87 100644 --- a/drivers/gpio/sunxi_gpio.c +++ b/drivers/gpio/sunxi_gpio.c @@ -172,6 +172,17 @@ int sunxi_name_to_gpio(const char *name) #endif #ifdef CONFIG_DM_GPIO +/* TODO(sjg@chromium.org): Remove this function and use device tree */ +int sunxi_name_to_gpio(const char *name) +{ + unsigned int gpio; + int ret; + + ret = gpio_lookup_name(name, NULL, NULL, &gpio); + + return ret ? ret : gpio; +} + static int sunxi_gpio_direction_input(struct udevice *dev, unsigned offset) { struct sunxi_gpio_platdata *plat = dev_get_platdata(dev); -- cgit v1.2.3 From 11d52a9da6d377f39217f2a96f2304f533f5af6d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 22 Apr 2015 11:29:38 +0200 Subject: sunxi: gpio: Add compatible strings for all supported SoCs We want to use driver-model/fdt with other model SoCs too, so add compatible strings for the other SoCs to the dm sunxi gpio code. Signed-off-by: Hans de Goede Reviewed-by: Simon Glass Acked-by: Ian Campbell --- drivers/gpio/sunxi_gpio.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c index 89209dfa87..e6a90b93af 100644 --- a/drivers/gpio/sunxi_gpio.c +++ b/drivers/gpio/sunxi_gpio.c @@ -322,7 +322,14 @@ static int gpio_sunxi_bind(struct udevice *parent) } static const struct udevice_id sunxi_gpio_ids[] = { + { .compatible = "allwinner,sun4i-a10-pinctrl" }, + { .compatible = "allwinner,sun5i-a10s-pinctrl" }, + { .compatible = "allwinner,sun5i-a13-pinctrl" }, + { .compatible = "allwinner,sun6i-a31-pinctrl" }, + { .compatible = "allwinner,sun6i-a31s-pinctrl" }, { .compatible = "allwinner,sun7i-a20-pinctrl" }, + { .compatible = "allwinner,sun8i-a23-pinctrl" }, + { .compatible = "allwinner,sun9i-a80-pinctrl" }, { } }; -- cgit v1.2.3 From 746c087bd3538dc2c2b744e44815a3d5ce94e3bc Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 22 Apr 2015 17:59:01 +0200 Subject: sunxi: gpio: Build sunxi_name_to_gpio_bank for driver-model code too When doing a driver-model enabled build we still need sunxi_name_to_gpio_bank (for now) for the mmc pinmux code in board/sunxi/board.c, so build it for driver-model enabled builds too. Signed-off-by: Hans de Goede Reviewed-by: Simon Glass Acked-by: Ian Campbell --- drivers/gpio/sunxi_gpio.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c index e6a90b93af..91af1a54ec 100644 --- a/drivers/gpio/sunxi_gpio.c +++ b/drivers/gpio/sunxi_gpio.c @@ -118,20 +118,6 @@ int gpio_set_value(unsigned gpio, int value) return sunxi_gpio_output(gpio, value); } -int sunxi_name_to_gpio_bank(const char *name) -{ - int group = 0; - - if (*name == 'P' || *name == 'p') - name++; - if (*name >= 'A') { - group = *name - (*name > 'a' ? 'a' : 'A'); - return group; - } - - return -1; -} - int sunxi_name_to_gpio(const char *name) { int group = 0; @@ -171,6 +157,20 @@ int sunxi_name_to_gpio(const char *name) } #endif +int sunxi_name_to_gpio_bank(const char *name) +{ + int group = 0; + + if (*name == 'P' || *name == 'p') + name++; + if (*name >= 'A') { + group = *name - (*name > 'a' ? 'a' : 'A'); + return group; + } + + return -1; +} + #ifdef CONFIG_DM_GPIO /* TODO(sjg@chromium.org): Remove this function and use device tree */ int sunxi_name_to_gpio(const char *name) -- cgit v1.2.3 From 12ce15538a4512834138ee4d0ded416286ec46ad Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 22 Apr 2015 16:27:01 +0200 Subject: sunxi: axp: Change axp_gpio_foo prototypes to match gpio uclass ops Change the axp_gpio_foo function prototypes to match the gpio uclass op prototypes, this is a preparation patch for moving the axp gpio code to a separate driver-model gpio driver. Note that the ugly calls with a NULL udev pointer in drivers/gpio/sunxi_gpio.c this adds are removed in a later patch. Signed-off-by: Hans de Goede Reviewed-by: Simon Glass Acked-by: Ian Campbell --- drivers/gpio/sunxi_gpio.c | 8 ++++---- drivers/power/axp209.c | 10 +++++----- drivers/power/axp221.c | 10 +++++----- 3 files changed, 14 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c index 91af1a54ec..0774b70934 100644 --- a/drivers/gpio/sunxi_gpio.c +++ b/drivers/gpio/sunxi_gpio.c @@ -81,7 +81,7 @@ int gpio_direction_input(unsigned gpio) { #ifdef AXP_GPIO if (gpio >= SUNXI_GPIO_AXP0_START) - return axp_gpio_direction_input(gpio - SUNXI_GPIO_AXP0_START); + return axp_gpio_direction_input(NULL, gpio - SUNXI_GPIO_AXP0_START); #endif sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_INPUT); @@ -92,7 +92,7 @@ int gpio_direction_output(unsigned gpio, int value) { #ifdef AXP_GPIO if (gpio >= SUNXI_GPIO_AXP0_START) - return axp_gpio_direction_output(gpio - SUNXI_GPIO_AXP0_START, + return axp_gpio_direction_output(NULL, gpio - SUNXI_GPIO_AXP0_START, value); #endif sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_OUTPUT); @@ -104,7 +104,7 @@ int gpio_get_value(unsigned gpio) { #ifdef AXP_GPIO if (gpio >= SUNXI_GPIO_AXP0_START) - return axp_gpio_get_value(gpio - SUNXI_GPIO_AXP0_START); + return axp_gpio_get_value(NULL, gpio - SUNXI_GPIO_AXP0_START); #endif return sunxi_gpio_input(gpio); } @@ -113,7 +113,7 @@ int gpio_set_value(unsigned gpio, int value) { #ifdef AXP_GPIO if (gpio >= SUNXI_GPIO_AXP0_START) - return axp_gpio_set_value(gpio - SUNXI_GPIO_AXP0_START, value); + return axp_gpio_set_value(NULL, gpio - SUNXI_GPIO_AXP0_START, value); #endif return sunxi_gpio_output(gpio, value); } diff --git a/drivers/power/axp209.c b/drivers/power/axp209.c index 1d7be4991a..98c214fa7a 100644 --- a/drivers/power/axp209.c +++ b/drivers/power/axp209.c @@ -167,7 +167,7 @@ static u8 axp209_get_gpio_ctrl_reg(unsigned int pin) return 0; } -int axp_gpio_direction_input(unsigned int pin) +int axp_gpio_direction_input(struct udevice *dev, unsigned pin) { if (pin == SUNXI_GPIO_AXP0_VBUS_DETECT) return 0; @@ -179,7 +179,7 @@ int axp_gpio_direction_input(unsigned int pin) return axp209_write(reg, val); } -int axp_gpio_direction_output(unsigned int pin, unsigned int val) +int axp_gpio_direction_output(struct udevice *dev, unsigned pin, int val) { u8 reg = axp209_get_gpio_ctrl_reg(pin); @@ -194,7 +194,7 @@ int axp_gpio_direction_output(unsigned int pin, unsigned int val) return axp209_write(reg, val); } -int axp_gpio_get_value(unsigned int pin) +int axp_gpio_get_value(struct udevice *dev, unsigned pin) { u8 val, mask; int rc; @@ -215,7 +215,7 @@ int axp_gpio_get_value(unsigned int pin) return (val & mask) ? 1 : 0; } -int axp_gpio_set_value(unsigned int pin, unsigned int val) +int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val) { - return axp_gpio_direction_output(pin, val); + return axp_gpio_direction_output(dev, pin, val); } diff --git a/drivers/power/axp221.c b/drivers/power/axp221.c index dc3a7f19bd..4970ab46ee 100644 --- a/drivers/power/axp221.c +++ b/drivers/power/axp221.c @@ -386,7 +386,7 @@ int axp221_get_sid(unsigned int *sid) return 0; } -int axp_gpio_direction_input(unsigned int pin) +int axp_gpio_direction_input(struct udevice *dev, unsigned pin) { switch (pin) { case SUNXI_GPIO_AXP0_VBUS_DETECT: @@ -396,7 +396,7 @@ int axp_gpio_direction_input(unsigned int pin) } } -int axp_gpio_direction_output(unsigned int pin, unsigned int val) +int axp_gpio_direction_output(struct udevice *dev, unsigned pin, int val) { int ret; @@ -407,13 +407,13 @@ int axp_gpio_direction_output(unsigned int pin, unsigned int val) if (ret) return ret; - return axp_gpio_set_value(pin, val); + return axp_gpio_set_value(dev, pin, val); default: return -EINVAL; } } -int axp_gpio_get_value(unsigned int pin) +int axp_gpio_get_value(struct udevice *dev, unsigned pin) { int ret; u8 val; @@ -430,7 +430,7 @@ int axp_gpio_get_value(unsigned int pin) } } -int axp_gpio_set_value(unsigned int pin, unsigned int val) +int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val) { int ret; -- cgit v1.2.3 From 1d624a4f08d3a478e38ceb1a048c3da4982021df Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 25 Apr 2015 14:07:37 +0200 Subject: sunxi: axp: Move axp pmic register helpers to a separate file Move the register helpers used to access the registers via p2wi resp. rsb bus on the otherwise identical axp221 and axp223 pmics to a separate file, so that they can be used by the upcoming standalone axp gpio driver too. Signed-off-by: Hans de Goede Reviewed-by: Simon Glass Acked-by: Ian Campbell --- drivers/power/axp221.c | 172 +++++++++++++++---------------------------------- 1 file changed, 53 insertions(+), 119 deletions(-) (limited to 'drivers') diff --git a/drivers/power/axp221.c b/drivers/power/axp221.c index 4970ab46ee..d49de86e97 100644 --- a/drivers/power/axp221.c +++ b/drivers/power/axp221.c @@ -12,50 +12,10 @@ #include #include -#include -#include #include +#include #include -/* - * The axp221 uses the p2wi bus, the axp223 is identical (for all registers - * used sofar) but uses the rsb bus. These functions abstract this. - */ -static int pmic_bus_init(void) -{ -#ifdef CONFIG_MACH_SUN6I - p2wi_init(); - return p2wi_change_to_p2wi_mode(AXP221_CHIP_ADDR, AXP221_CTRL_ADDR, - AXP221_INIT_DATA); -#else - int ret; - - ret = rsb_init(); - if (ret) - return ret; - - return rsb_set_device_address(AXP223_DEVICE_ADDR, AXP223_RUNTIME_ADDR); -#endif -} - -static int pmic_bus_read(const u8 addr, u8 *data) -{ -#ifdef CONFIG_MACH_SUN6I - return p2wi_read(addr, data); -#else - return rsb_read(AXP223_RUNTIME_ADDR, addr, data); -#endif -} - -static int pmic_bus_write(const u8 addr, u8 data) -{ -#ifdef CONFIG_MACH_SUN6I - return p2wi_write(addr, data); -#else - return rsb_write(AXP223_RUNTIME_ADDR, addr, data); -#endif -} - static u8 axp221_mvolt_to_cfg(int mvolt, int min, int max, int div) { if (mvolt < min) @@ -66,52 +26,26 @@ static u8 axp221_mvolt_to_cfg(int mvolt, int min, int max, int div) return (mvolt - min) / div; } -static int axp221_setbits(u8 reg, u8 bits) -{ - int ret; - u8 val; - - ret = pmic_bus_read(reg, &val); - if (ret) - return ret; - - val |= bits; - return pmic_bus_write(reg, val); -} - -static int axp221_clrbits(u8 reg, u8 bits) -{ - int ret; - u8 val; - - ret = pmic_bus_read(reg, &val); - if (ret) - return ret; - - val &= ~bits; - return pmic_bus_write(reg, val); -} - int axp221_set_dcdc1(unsigned int mvolt) { int ret; u8 cfg = axp221_mvolt_to_cfg(mvolt, 1600, 3400, 100); if (mvolt == 0) - return axp221_clrbits(AXP221_OUTPUT_CTRL1, - AXP221_OUTPUT_CTRL1_DCDC1_EN); + return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1, + AXP221_OUTPUT_CTRL1_DCDC1_EN); ret = pmic_bus_write(AXP221_DCDC1_CTRL, cfg); if (ret) return ret; - ret = axp221_setbits(AXP221_OUTPUT_CTRL2, - AXP221_OUTPUT_CTRL2_DCDC1SW_EN); + ret = pmic_bus_setbits(AXP221_OUTPUT_CTRL2, + AXP221_OUTPUT_CTRL2_DCDC1SW_EN); if (ret) return ret; - return axp221_setbits(AXP221_OUTPUT_CTRL1, - AXP221_OUTPUT_CTRL1_DCDC1_EN); + return pmic_bus_setbits(AXP221_OUTPUT_CTRL1, + AXP221_OUTPUT_CTRL1_DCDC1_EN); } int axp221_set_dcdc2(unsigned int mvolt) @@ -120,15 +54,15 @@ int axp221_set_dcdc2(unsigned int mvolt) u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20); if (mvolt == 0) - return axp221_clrbits(AXP221_OUTPUT_CTRL1, - AXP221_OUTPUT_CTRL1_DCDC2_EN); + return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1, + AXP221_OUTPUT_CTRL1_DCDC2_EN); ret = pmic_bus_write(AXP221_DCDC2_CTRL, cfg); if (ret) return ret; - return axp221_setbits(AXP221_OUTPUT_CTRL1, - AXP221_OUTPUT_CTRL1_DCDC2_EN); + return pmic_bus_setbits(AXP221_OUTPUT_CTRL1, + AXP221_OUTPUT_CTRL1_DCDC2_EN); } int axp221_set_dcdc3(unsigned int mvolt) @@ -137,15 +71,15 @@ int axp221_set_dcdc3(unsigned int mvolt) u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1860, 20); if (mvolt == 0) - return axp221_clrbits(AXP221_OUTPUT_CTRL1, - AXP221_OUTPUT_CTRL1_DCDC3_EN); + return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1, + AXP221_OUTPUT_CTRL1_DCDC3_EN); ret = pmic_bus_write(AXP221_DCDC3_CTRL, cfg); if (ret) return ret; - return axp221_setbits(AXP221_OUTPUT_CTRL1, - AXP221_OUTPUT_CTRL1_DCDC3_EN); + return pmic_bus_setbits(AXP221_OUTPUT_CTRL1, + AXP221_OUTPUT_CTRL1_DCDC3_EN); } int axp221_set_dcdc4(unsigned int mvolt) @@ -154,15 +88,15 @@ int axp221_set_dcdc4(unsigned int mvolt) u8 cfg = axp221_mvolt_to_cfg(mvolt, 600, 1540, 20); if (mvolt == 0) - return axp221_clrbits(AXP221_OUTPUT_CTRL1, - AXP221_OUTPUT_CTRL1_DCDC4_EN); + return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1, + AXP221_OUTPUT_CTRL1_DCDC4_EN); ret = pmic_bus_write(AXP221_DCDC4_CTRL, cfg); if (ret) return ret; - return axp221_setbits(AXP221_OUTPUT_CTRL1, - AXP221_OUTPUT_CTRL1_DCDC4_EN); + return pmic_bus_setbits(AXP221_OUTPUT_CTRL1, + AXP221_OUTPUT_CTRL1_DCDC4_EN); } int axp221_set_dcdc5(unsigned int mvolt) @@ -171,15 +105,15 @@ int axp221_set_dcdc5(unsigned int mvolt) u8 cfg = axp221_mvolt_to_cfg(mvolt, 1000, 2550, 50); if (mvolt == 0) - return axp221_clrbits(AXP221_OUTPUT_CTRL1, - AXP221_OUTPUT_CTRL1_DCDC5_EN); + return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1, + AXP221_OUTPUT_CTRL1_DCDC5_EN); ret = pmic_bus_write(AXP221_DCDC5_CTRL, cfg); if (ret) return ret; - return axp221_setbits(AXP221_OUTPUT_CTRL1, - AXP221_OUTPUT_CTRL1_DCDC5_EN); + return pmic_bus_setbits(AXP221_OUTPUT_CTRL1, + AXP221_OUTPUT_CTRL1_DCDC5_EN); } int axp221_set_dldo1(unsigned int mvolt) @@ -188,15 +122,15 @@ int axp221_set_dldo1(unsigned int mvolt) u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); if (mvolt == 0) - return axp221_clrbits(AXP221_OUTPUT_CTRL2, - AXP221_OUTPUT_CTRL2_DLDO1_EN); + return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2, + AXP221_OUTPUT_CTRL2_DLDO1_EN); ret = pmic_bus_write(AXP221_DLDO1_CTRL, cfg); if (ret) return ret; - return axp221_setbits(AXP221_OUTPUT_CTRL2, - AXP221_OUTPUT_CTRL2_DLDO1_EN); + return pmic_bus_setbits(AXP221_OUTPUT_CTRL2, + AXP221_OUTPUT_CTRL2_DLDO1_EN); } int axp221_set_dldo2(unsigned int mvolt) @@ -205,15 +139,15 @@ int axp221_set_dldo2(unsigned int mvolt) u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); if (mvolt == 0) - return axp221_clrbits(AXP221_OUTPUT_CTRL2, - AXP221_OUTPUT_CTRL2_DLDO2_EN); + return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2, + AXP221_OUTPUT_CTRL2_DLDO2_EN); ret = pmic_bus_write(AXP221_DLDO2_CTRL, cfg); if (ret) return ret; - return axp221_setbits(AXP221_OUTPUT_CTRL2, - AXP221_OUTPUT_CTRL2_DLDO2_EN); + return pmic_bus_setbits(AXP221_OUTPUT_CTRL2, + AXP221_OUTPUT_CTRL2_DLDO2_EN); } int axp221_set_dldo3(unsigned int mvolt) @@ -222,15 +156,15 @@ int axp221_set_dldo3(unsigned int mvolt) u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); if (mvolt == 0) - return axp221_clrbits(AXP221_OUTPUT_CTRL2, - AXP221_OUTPUT_CTRL2_DLDO3_EN); + return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2, + AXP221_OUTPUT_CTRL2_DLDO3_EN); ret = pmic_bus_write(AXP221_DLDO3_CTRL, cfg); if (ret) return ret; - return axp221_setbits(AXP221_OUTPUT_CTRL2, - AXP221_OUTPUT_CTRL2_DLDO3_EN); + return pmic_bus_setbits(AXP221_OUTPUT_CTRL2, + AXP221_OUTPUT_CTRL2_DLDO3_EN); } int axp221_set_dldo4(unsigned int mvolt) @@ -239,15 +173,15 @@ int axp221_set_dldo4(unsigned int mvolt) u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); if (mvolt == 0) - return axp221_clrbits(AXP221_OUTPUT_CTRL2, - AXP221_OUTPUT_CTRL2_DLDO4_EN); + return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2, + AXP221_OUTPUT_CTRL2_DLDO4_EN); ret = pmic_bus_write(AXP221_DLDO4_CTRL, cfg); if (ret) return ret; - return axp221_setbits(AXP221_OUTPUT_CTRL2, - AXP221_OUTPUT_CTRL2_DLDO4_EN); + return pmic_bus_setbits(AXP221_OUTPUT_CTRL2, + AXP221_OUTPUT_CTRL2_DLDO4_EN); } int axp221_set_aldo1(unsigned int mvolt) @@ -256,15 +190,15 @@ int axp221_set_aldo1(unsigned int mvolt) u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); if (mvolt == 0) - return axp221_clrbits(AXP221_OUTPUT_CTRL1, - AXP221_OUTPUT_CTRL1_ALDO1_EN); + return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1, + AXP221_OUTPUT_CTRL1_ALDO1_EN); ret = pmic_bus_write(AXP221_ALDO1_CTRL, cfg); if (ret) return ret; - return axp221_setbits(AXP221_OUTPUT_CTRL1, - AXP221_OUTPUT_CTRL1_ALDO1_EN); + return pmic_bus_setbits(AXP221_OUTPUT_CTRL1, + AXP221_OUTPUT_CTRL1_ALDO1_EN); } int axp221_set_aldo2(unsigned int mvolt) @@ -273,15 +207,15 @@ int axp221_set_aldo2(unsigned int mvolt) u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); if (mvolt == 0) - return axp221_clrbits(AXP221_OUTPUT_CTRL1, - AXP221_OUTPUT_CTRL1_ALDO2_EN); + return pmic_bus_clrbits(AXP221_OUTPUT_CTRL1, + AXP221_OUTPUT_CTRL1_ALDO2_EN); ret = pmic_bus_write(AXP221_ALDO2_CTRL, cfg); if (ret) return ret; - return axp221_setbits(AXP221_OUTPUT_CTRL1, - AXP221_OUTPUT_CTRL1_ALDO2_EN); + return pmic_bus_setbits(AXP221_OUTPUT_CTRL1, + AXP221_OUTPUT_CTRL1_ALDO2_EN); } int axp221_set_aldo3(unsigned int mvolt) @@ -290,15 +224,15 @@ int axp221_set_aldo3(unsigned int mvolt) u8 cfg = axp221_mvolt_to_cfg(mvolt, 700, 3300, 100); if (mvolt == 0) - return axp221_clrbits(AXP221_OUTPUT_CTRL3, - AXP221_OUTPUT_CTRL3_ALDO3_EN); + return pmic_bus_clrbits(AXP221_OUTPUT_CTRL3, + AXP221_OUTPUT_CTRL3_ALDO3_EN); ret = pmic_bus_write(AXP221_ALDO3_CTRL, cfg); if (ret) return ret; - return axp221_setbits(AXP221_OUTPUT_CTRL3, - AXP221_OUTPUT_CTRL3_ALDO3_EN); + return pmic_bus_setbits(AXP221_OUTPUT_CTRL3, + AXP221_OUTPUT_CTRL3_ALDO3_EN); } int axp221_set_eldo(int eldo_num, unsigned int mvolt) @@ -325,13 +259,13 @@ int axp221_set_eldo(int eldo_num, unsigned int mvolt) } if (mvolt == 0) - return axp221_clrbits(AXP221_OUTPUT_CTRL2, bits); + return pmic_bus_clrbits(AXP221_OUTPUT_CTRL2, bits); ret = pmic_bus_write(addr, cfg); if (ret) return ret; - return axp221_setbits(AXP221_OUTPUT_CTRL2, bits); + return pmic_bus_setbits(AXP221_OUTPUT_CTRL2, bits); } int axp221_init(void) -- cgit v1.2.3 From 2fcf033d36618da4c86de135a0d447fd3bbaf8ea Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 25 Apr 2015 17:25:14 +0200 Subject: sunxi: axp: Move axp gpio code to a separate axpi-gpio driver Move the axp-gpio code out of the drivers/power/axp*.c code, and into a new separate axpi-gpio driver. This change drops supports for the gpio3 pin on the axp209, as that requires special handling, and no boards are using it. Besides cleaning things up by moving the code to a separate driver, as a bonus this change also adds support for the (non vusb) gpio pins on the axp221 and the gpio pins on the axp152. The new axp-gpio driver gets its own Kconfig option, and is only enabled on boards which need it. Besides that it only gets enabled in the regular u-boot build and not for the SPL as we never need it in the SPL. Signed-off-by: Hans de Goede Reviewed-by: Simon Glass Acked-by: Ian Campbell --- drivers/gpio/Makefile | 1 + drivers/gpio/axp_gpio.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/gpio/sunxi_gpio.c | 17 ++---- drivers/power/axp209.c | 64 -------------------- drivers/power/axp221.c | 64 -------------------- 5 files changed, 154 insertions(+), 139 deletions(-) create mode 100644 drivers/gpio/axp_gpio.c (limited to 'drivers') diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index fb40e09020..ba9efe8d54 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -7,6 +7,7 @@ ifndef CONFIG_SPL_BUILD obj-$(CONFIG_DM_GPIO) += gpio-uclass.o +obj-$(CONFIG_AXP_GPIO) += axp_gpio.o endif /* TODO(sjg@chromium.org): Only tegra supports driver model in SPL */ ifdef CONFIG_TEGRA_GPIO diff --git a/drivers/gpio/axp_gpio.c b/drivers/gpio/axp_gpio.c new file mode 100644 index 0000000000..d04ec221ac --- /dev/null +++ b/drivers/gpio/axp_gpio.c @@ -0,0 +1,147 @@ +/* + * (C) Copyright 2015 Hans de Goede + * + * X-Powers AXP Power Management ICs gpio driver + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include + +#ifdef CONFIG_AXP152_POWER +#include +#elif defined CONFIG_AXP209_POWER +#include +#elif defined CONFIG_AXP221_POWER +#include +#else +#error Unknown AXP model +#endif + +static u8 axp_get_gpio_ctrl_reg(unsigned pin) +{ + switch (pin) { + case 0: return AXP_GPIO0_CTRL; + case 1: return AXP_GPIO1_CTRL; +#ifdef AXP_GPIO2_CTRL + case 2: return AXP_GPIO2_CTRL; +#endif +#ifdef AXP_GPIO3_CTRL + case 3: return AXP_GPIO3_CTRL; +#endif + } + return 0; +} + +int axp_gpio_direction_input(struct udevice *dev, unsigned pin) +{ + u8 reg; + + switch (pin) { +#ifndef CONFIG_AXP152_POWER /* NA on axp152 */ + case SUNXI_GPIO_AXP0_VBUS_DETECT: + return 0; +#endif + default: + reg = axp_get_gpio_ctrl_reg(pin); + if (reg == 0) + return -EINVAL; + + return pmic_bus_write(reg, AXP_GPIO_CTRL_INPUT); + } +} + +int axp_gpio_direction_output(struct udevice *dev, unsigned pin, int val) +{ + __maybe_unused int ret; + u8 reg; + + switch (pin) { +#ifdef CONFIG_AXP221_POWER /* Only available on axp221/axp223 */ + case SUNXI_GPIO_AXP0_VBUS_ENABLE: + ret = pmic_bus_clrbits(AXP221_MISC_CTRL, + AXP221_MISC_CTRL_N_VBUSEN_FUNC); + if (ret) + return ret; + + return axp_gpio_set_value(dev, pin, val); +#endif + default: + reg = axp_get_gpio_ctrl_reg(pin); + if (reg == 0) + return -EINVAL; + + return pmic_bus_write(reg, val ? AXP_GPIO_CTRL_OUTPUT_HIGH : + AXP_GPIO_CTRL_OUTPUT_LOW); + } +} + +int axp_gpio_get_value(struct udevice *dev, unsigned pin) +{ + u8 reg, val, mask; + int ret; + + switch (pin) { +#ifndef CONFIG_AXP152_POWER /* NA on axp152 */ + case SUNXI_GPIO_AXP0_VBUS_DETECT: + ret = pmic_bus_read(AXP_POWER_STATUS, &val); + mask = AXP_POWER_STATUS_VBUS_PRESENT; + break; +#endif +#ifdef CONFIG_AXP221_POWER /* Only available on axp221/axp223 */ + case SUNXI_GPIO_AXP0_VBUS_ENABLE: + ret = pmic_bus_read(AXP221_VBUS_IPSOUT, &val); + mask = AXP221_VBUS_IPSOUT_DRIVEBUS; + break; +#endif + default: + reg = axp_get_gpio_ctrl_reg(pin); + if (reg == 0) + return -EINVAL; + + ret = pmic_bus_read(AXP_GPIO_STATE, &val); + mask = 1 << (pin + AXP_GPIO_STATE_OFFSET); + } + if (ret) + return ret; + + return (val & mask) ? 1 : 0; +} + +int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val) +{ + u8 reg; + + switch (pin) { +#ifdef CONFIG_AXP221_POWER /* Only available on axp221/axp223 */ + case SUNXI_GPIO_AXP0_VBUS_ENABLE: + if (val) + return pmic_bus_setbits(AXP221_VBUS_IPSOUT, + AXP221_VBUS_IPSOUT_DRIVEBUS); + else + return pmic_bus_clrbits(AXP221_VBUS_IPSOUT, + AXP221_VBUS_IPSOUT_DRIVEBUS); +#endif + default: + reg = axp_get_gpio_ctrl_reg(pin); + if (reg == 0) + return -EINVAL; + + return pmic_bus_write(reg, val ? AXP_GPIO_CTRL_OUTPUT_HIGH : + AXP_GPIO_CTRL_OUTPUT_LOW); + } +} + +int axp_gpio_init(void) +{ + int ret; + + ret = pmic_bus_init(); + if (ret) + return ret; + + return 0; +} diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c index 0774b70934..5a0b5e4aee 100644 --- a/drivers/gpio/sunxi_gpio.c +++ b/drivers/gpio/sunxi_gpio.c @@ -15,15 +15,10 @@ #include #include #include +#include #include #include #include -#ifdef CONFIG_AXP209_POWER -#include -#endif -#ifdef CONFIG_AXP221_POWER -#include -#endif DECLARE_GLOBAL_DATA_PTR; @@ -79,7 +74,7 @@ int gpio_free(unsigned gpio) int gpio_direction_input(unsigned gpio) { -#ifdef AXP_GPIO +#if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO if (gpio >= SUNXI_GPIO_AXP0_START) return axp_gpio_direction_input(NULL, gpio - SUNXI_GPIO_AXP0_START); #endif @@ -90,7 +85,7 @@ int gpio_direction_input(unsigned gpio) int gpio_direction_output(unsigned gpio, int value) { -#ifdef AXP_GPIO +#if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO if (gpio >= SUNXI_GPIO_AXP0_START) return axp_gpio_direction_output(NULL, gpio - SUNXI_GPIO_AXP0_START, value); @@ -102,7 +97,7 @@ int gpio_direction_output(unsigned gpio, int value) int gpio_get_value(unsigned gpio) { -#ifdef AXP_GPIO +#if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO if (gpio >= SUNXI_GPIO_AXP0_START) return axp_gpio_get_value(NULL, gpio - SUNXI_GPIO_AXP0_START); #endif @@ -111,7 +106,7 @@ int gpio_get_value(unsigned gpio) int gpio_set_value(unsigned gpio, int value) { -#ifdef AXP_GPIO +#if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO if (gpio >= SUNXI_GPIO_AXP0_START) return axp_gpio_set_value(NULL, gpio - SUNXI_GPIO_AXP0_START, value); #endif @@ -125,7 +120,7 @@ int sunxi_name_to_gpio(const char *name) long pin; char *eptr; -#ifdef AXP_GPIO +#if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO if (strncasecmp(name, "AXP0-", 5) == 0) { name += 5; if (strcmp(name, "VBUS-DETECT") == 0) diff --git a/drivers/power/axp209.c b/drivers/power/axp209.c index 98c214fa7a..5161bc1472 100644 --- a/drivers/power/axp209.c +++ b/drivers/power/axp209.c @@ -155,67 +155,3 @@ int axp209_power_button(void) return v & AXP209_IRQ5_PEK_DOWN; } - -static u8 axp209_get_gpio_ctrl_reg(unsigned int pin) -{ - switch (pin) { - case 0: return AXP209_GPIO0_CTRL; - case 1: return AXP209_GPIO1_CTRL; - case 2: return AXP209_GPIO2_CTRL; - case 3: return AXP209_GPIO3_CTRL; - } - return 0; -} - -int axp_gpio_direction_input(struct udevice *dev, unsigned pin) -{ - if (pin == SUNXI_GPIO_AXP0_VBUS_DETECT) - return 0; - - u8 reg = axp209_get_gpio_ctrl_reg(pin); - /* GPIO3 is "special" */ - u8 val = (pin == 3) ? AXP209_GPIO3_INPUT : AXP209_GPIO_INPUT; - - return axp209_write(reg, val); -} - -int axp_gpio_direction_output(struct udevice *dev, unsigned pin, int val) -{ - u8 reg = axp209_get_gpio_ctrl_reg(pin); - - if (val) { - val = (pin == 3) ? AXP209_GPIO3_OUTPUT_HIGH : - AXP209_GPIO_OUTPUT_HIGH; - } else { - val = (pin == 3) ? AXP209_GPIO3_OUTPUT_LOW : - AXP209_GPIO_OUTPUT_LOW; - } - - return axp209_write(reg, val); -} - -int axp_gpio_get_value(struct udevice *dev, unsigned pin) -{ - u8 val, mask; - int rc; - - if (pin == SUNXI_GPIO_AXP0_VBUS_DETECT) { - rc = axp209_read(AXP209_POWER_STATUS, &val); - mask = AXP209_POWER_STATUS_VBUS_USABLE; - } else if (pin == 3) { - rc = axp209_read(AXP209_GPIO3_CTRL, &val); - mask = 1; - } else { - rc = axp209_read(AXP209_GPIO_STATE, &val); - mask = 1 << (pin + 4); - } - if (rc) - return rc; - - return (val & mask) ? 1 : 0; -} - -int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val) -{ - return axp_gpio_direction_output(dev, pin, val); -} diff --git a/drivers/power/axp221.c b/drivers/power/axp221.c index d49de86e97..7bbaec87e4 100644 --- a/drivers/power/axp221.c +++ b/drivers/power/axp221.c @@ -319,67 +319,3 @@ int axp221_get_sid(unsigned int *sid) return 0; } - -int axp_gpio_direction_input(struct udevice *dev, unsigned pin) -{ - switch (pin) { - case SUNXI_GPIO_AXP0_VBUS_DETECT: - return 0; - default: - return -EINVAL; - } -} - -int axp_gpio_direction_output(struct udevice *dev, unsigned pin, int val) -{ - int ret; - - switch (pin) { - case SUNXI_GPIO_AXP0_VBUS_ENABLE: - ret = axp221_clrbits(AXP221_MISC_CTRL, - AXP221_MISC_CTRL_N_VBUSEN_FUNC); - if (ret) - return ret; - - return axp_gpio_set_value(dev, pin, val); - default: - return -EINVAL; - } -} - -int axp_gpio_get_value(struct udevice *dev, unsigned pin) -{ - int ret; - u8 val; - - switch (pin) { - case SUNXI_GPIO_AXP0_VBUS_DETECT: - ret = pmic_bus_read(AXP221_POWER_STATUS, &val); - if (ret) - return ret; - - return !!(val & AXP221_POWER_STATUS_VBUS_AVAIL); - default: - return -EINVAL; - } -} - -int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val) -{ - int ret; - - switch (pin) { - case SUNXI_GPIO_AXP0_VBUS_ENABLE: - if (val) - ret = axp221_setbits(AXP221_VBUS_IPSOUT, - AXP221_VBUS_IPSOUT_DRIVEBUS); - else - ret = axp221_clrbits(AXP221_VBUS_IPSOUT, - AXP221_VBUS_IPSOUT_DRIVEBUS); - - if (ret) - return ret; - } - - return 0; -} -- cgit v1.2.3 From f9b7a04bc8aae9b1ffe35c8cc90e1a59f618a9ab Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 22 Apr 2015 11:31:22 +0200 Subject: sunxi: axp: Add driver-model support to the axp_gpio code Add driver-model support to the axp_gpio code, note that this needs a small tweak to the driver-model version of sunxi_name_to_gpio to deal with the vbus detect and enable pins which are not standard numbered gpios. Signed-off-by: Hans de Goede Reviewed-by: Simon Glass Acked-by: Ian Campbell --- drivers/gpio/axp_gpio.c | 40 ++++++++++++++++++++++++++++++++++++++++ drivers/gpio/sunxi_gpio.c | 14 +++++++++++++- 2 files changed, 53 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/axp_gpio.c b/drivers/gpio/axp_gpio.c index d04ec221ac..55f20a34b6 100644 --- a/drivers/gpio/axp_gpio.c +++ b/drivers/gpio/axp_gpio.c @@ -9,6 +9,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #ifdef CONFIG_AXP152_POWER @@ -135,13 +140,48 @@ int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val) } } +#ifdef CONFIG_DM_GPIO +static const struct dm_gpio_ops gpio_axp_ops = { + .direction_input = axp_gpio_direction_input, + .direction_output = axp_gpio_direction_output, + .get_value = axp_gpio_get_value, + .set_value = axp_gpio_set_value, +}; + +static int gpio_axp_probe(struct udevice *dev) +{ + struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev); + + /* Tell the uclass how many GPIOs we have */ + uc_priv->bank_name = strdup(SUNXI_GPIO_AXP0_PREFIX); + uc_priv->gpio_count = SUNXI_GPIO_AXP0_GPIO_COUNT; + + return 0; +} + +U_BOOT_DRIVER(gpio_axp) = { + .name = "gpio_axp", + .id = UCLASS_GPIO, + .ops = &gpio_axp_ops, + .probe = gpio_axp_probe, +}; +#endif + int axp_gpio_init(void) { + __maybe_unused struct udevice *dev; int ret; ret = pmic_bus_init(); if (ret) return ret; +#ifdef CONFIG_DM_GPIO + /* There is no devicetree support for the axp yet, so bind directly */ + ret = device_bind_driver(dm_root(), "gpio_axp", "AXP-gpio", &dev); + if (ret) + return ret; +#endif + return 0; } diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c index 5a0b5e4aee..21c3ff1e75 100644 --- a/drivers/gpio/sunxi_gpio.c +++ b/drivers/gpio/sunxi_gpio.c @@ -172,7 +172,19 @@ int sunxi_name_to_gpio(const char *name) { unsigned int gpio; int ret; - +#if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO + char lookup[8]; + + if (strcasecmp(name, "AXP0-VBUS-DETECT") == 0) { + sprintf(lookup, SUNXI_GPIO_AXP0_PREFIX "%d", + SUNXI_GPIO_AXP0_VBUS_DETECT); + name = lookup; + } else if (strcasecmp(name, "AXP0-VBUS-ENABLE") == 0) { + sprintf(lookup, SUNXI_GPIO_AXP0_PREFIX "%d", + SUNXI_GPIO_AXP0_VBUS_ENABLE); + name = lookup; + } +#endif ret = gpio_lookup_name(name, NULL, NULL, &gpio); return ret ? ret : gpio; -- cgit v1.2.3 From 8145dea46801e14af3bf65d2d70c3c19b8bb8e81 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 16 Apr 2015 21:47:06 +0200 Subject: sunxi: emac: port to phylib This is a preparation-patch for adding device-model support to the emac driver. Signed-off-by: Hans de Goede Acked-by: Ian Campbell Reviewed-by: Stefan Roese --- drivers/net/sunxi_emac.c | 111 +++++++++++++++++++++++++++++------------------ 1 file changed, 69 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c index 7b31f8c1da..b9fd1b854a 100644 --- a/drivers/net/sunxi_emac.c +++ b/drivers/net/sunxi_emac.c @@ -156,9 +156,9 @@ struct sunxi_sramc_regs { #define DMA_CPU_TRRESHOLD 2000 struct emac_eth_dev { - u32 speed; - u32 duplex; - u32 phy_configured; + struct emac_regs *regs; + struct mii_dev *bus; + struct phy_device *phydev; int link_printed; }; @@ -195,11 +195,10 @@ static void emac_outblk_32bit(void *reg, void *data, int count) } /* Read a word from phyxcer */ -static int emac_phy_read(const char *devname, unsigned char addr, - unsigned char reg, unsigned short *value) +static int emac_mdio_read(struct mii_dev *bus, int addr, int devad, int reg) { - struct eth_device *dev = eth_get_dev_by_name(devname); - struct emac_regs *regs = (struct emac_regs *)dev->iobase; + struct emac_eth_dev *priv = bus->priv; + struct emac_regs *regs = priv->regs; /* issue the phy address and reg */ writel(addr << 8 | reg, ®s->mac_madr); @@ -213,18 +212,16 @@ static int emac_phy_read(const char *devname, unsigned char addr, /* push down the phy io line */ writel(0x0, ®s->mac_mcmd); - /* and write data */ - *value = readl(®s->mac_mrdd); - - return 0; + /* And read data */ + return readl(®s->mac_mrdd); } /* Write a word to phyxcer */ -static int emac_phy_write(const char *devname, unsigned char addr, - unsigned char reg, unsigned short value) +static int emac_mdio_write(struct mii_dev *bus, int addr, int devad, int reg, + u16 value) { - struct eth_device *dev = eth_get_dev_by_name(devname); - struct emac_regs *regs = (struct emac_regs *)dev->iobase; + struct emac_eth_dev *priv = bus->priv; + struct emac_regs *regs = priv->regs; /* issue the phy address and reg */ writel(addr << 8 | reg, ®s->mac_madr); @@ -244,12 +241,44 @@ static int emac_phy_write(const char *devname, unsigned char addr, return 0; } -static void emac_setup(struct eth_device *dev) +static int sunxi_emac_init_phy(struct emac_eth_dev *priv, void *dev) { - struct emac_regs *regs = (struct emac_regs *)dev->iobase; + int ret, mask = 0xffffffff; + +#ifdef CONFIG_PHY_ADDR + mask = 1 << CONFIG_PHY_ADDR; +#endif + + priv->bus = mdio_alloc(); + if (!priv->bus) { + printf("Failed to allocate MDIO bus\n"); + return -ENOMEM; + } + + priv->bus->read = emac_mdio_read; + priv->bus->write = emac_mdio_write; + priv->bus->priv = priv; + strcpy(priv->bus->name, "emac"); + + ret = mdio_register(priv->bus); + if (ret) + return ret; + + priv->phydev = phy_find_by_mask(priv->bus, mask, + PHY_INTERFACE_MODE_MII); + if (!priv->phydev) + return -ENODEV; + + phy_connect_dev(priv->phydev, dev); + phy_config(priv->phydev); + + return 0; +} + +static void emac_setup(struct emac_eth_dev *priv) +{ + struct emac_regs *regs = priv->regs; u32 reg_val; - u16 phy_val; - u32 duplex_flag; /* Set up TX */ writel(EMAC_TX_SETUP, ®s->tx_mode); @@ -262,12 +291,8 @@ static void emac_setup(struct eth_device *dev) writel(EMAC_MAC_CTL0_SETUP, ®s->mac_ctl0); /* Set MAC CTL1 */ - emac_phy_read(dev->name, 1, 0, &phy_val); - debug("PHY SETUP, reg 0 value: %x\n", phy_val); - duplex_flag = !!(phy_val & (1 << 8)); - reg_val = 0; - if (duplex_flag) + if (priv->phydev->duplex == DUPLEX_FULL) reg_val = (0x1 << 0); writel(EMAC_MAC_CTL1_SETUP | reg_val, ®s->mac_ctl1); @@ -302,7 +327,7 @@ static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bd) { struct emac_regs *regs = (struct emac_regs *)dev->iobase; struct emac_eth_dev *priv = dev->priv; - u16 phy_reg; + int ret; /* Init EMAC */ @@ -320,7 +345,7 @@ static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bd) udelay(1); /* Set up EMAC */ - emac_setup(dev); + emac_setup(priv); writel(dev->enetaddr[0] << 16 | dev->enetaddr[1] << 8 | dev->enetaddr[2], ®s->mac_a1); @@ -332,29 +357,32 @@ static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bd) emac_reset(dev); /* PHY POWER UP */ - emac_phy_read(dev->name, 1, 0, &phy_reg); - emac_phy_write(dev->name, 1, 0, phy_reg & (~(0x1 << 11))); - mdelay(1); - - emac_phy_read(dev->name, 1, 0, &phy_reg); - - priv->speed = miiphy_speed(dev->name, 0); - priv->duplex = miiphy_duplex(dev->name, 0); + ret = phy_startup(priv->phydev); + if (ret) { + printf("Could not initialize PHY %s\n", + priv->phydev->dev->name); + return ret; + } /* Print link status only once */ if (!priv->link_printed) { printf("ENET Speed is %d Mbps - %s duplex connection\n", - priv->speed, (priv->duplex == HALF) ? "HALF" : "FULL"); + priv->phydev->speed, + priv->phydev->duplex ? "FULL" : "HALF"); priv->link_printed = 1; } /* Set EMAC SPEED depend on PHY */ - clrsetbits_le32(®s->mac_supp, 1 << 8, - ((phy_reg & (0x1 << 13)) >> 13) << 8); + if (priv->phydev->speed == SPEED_100) + setbits_le32(®s->mac_supp, 1 << 8); + else + clrbits_le32(®s->mac_supp, 1 << 8); /* Set duplex depend on phy */ - clrsetbits_le32(®s->mac_ctl1, 1 << 0, - ((phy_reg & (0x1 << 8)) >> 8) << 0); + if (priv->phydev->duplex == DUPLEX_FULL) + setbits_le32(®s->mac_ctl1, 1 << 0); + else + clrbits_le32(®s->mac_ctl1, 1 << 0); /* Enable RX/TX */ setbits_le32(®s->ctl, 0x7); @@ -505,6 +533,7 @@ int sunxi_emac_initialize(void) /* Set MII clock */ clrsetbits_le32(®s->mac_mcfg, 0xf << 2, 0xd << 2); + priv->regs = regs; dev->iobase = (int)regs; dev->priv = priv; dev->init = sunxi_emac_eth_init; @@ -515,7 +544,5 @@ int sunxi_emac_initialize(void) eth_register(dev); - miiphy_register(dev->name, emac_phy_read, emac_phy_write); - - return 0; + return sunxi_emac_init_phy(priv, dev); } -- cgit v1.2.3 From f9f62d2dac076de247461155f62906e0104259b0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 18 Apr 2015 14:44:38 +0200 Subject: sunxi: emac: Prepare for driver-model support Split all the core functionality out into functions taking a struct emac_eth_dev *priv argument as preparation for adding driver-model support. Signed-off-by: Hans de Goede Acked-by: Ian Campbell Reviewed-by: Stefan Roese --- drivers/net/sunxi_emac.c | 115 +++++++++++++++++++++++++++++------------------ 1 file changed, 71 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c index b9fd1b854a..038f474d25 100644 --- a/drivers/net/sunxi_emac.c +++ b/drivers/net/sunxi_emac.c @@ -309,9 +309,9 @@ static void emac_setup(struct emac_eth_dev *priv) writel(EMAC_MAC_MFL, ®s->mac_maxf); } -static void emac_reset(struct eth_device *dev) +static void emac_reset(struct emac_eth_dev *priv) { - struct emac_regs *regs = (struct emac_regs *)dev->iobase; + struct emac_regs *regs = priv->regs; debug("resetting device\n"); @@ -323,10 +323,9 @@ static void emac_reset(struct eth_device *dev) udelay(200); } -static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bd) +static int _sunxi_emac_eth_init(struct emac_eth_dev *priv, u8 *enetaddr) { - struct emac_regs *regs = (struct emac_regs *)dev->iobase; - struct emac_eth_dev *priv = dev->priv; + struct emac_regs *regs = priv->regs; int ret; /* Init EMAC */ @@ -347,14 +346,14 @@ static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bd) /* Set up EMAC */ emac_setup(priv); - writel(dev->enetaddr[0] << 16 | dev->enetaddr[1] << 8 | - dev->enetaddr[2], ®s->mac_a1); - writel(dev->enetaddr[3] << 16 | dev->enetaddr[4] << 8 | - dev->enetaddr[5], ®s->mac_a0); + writel(enetaddr[0] << 16 | enetaddr[1] << 8 | enetaddr[2], + ®s->mac_a1); + writel(enetaddr[3] << 16 | enetaddr[4] << 8 | enetaddr[5], + ®s->mac_a0); mdelay(1); - emac_reset(dev); + emac_reset(priv); /* PHY POWER UP */ ret = phy_startup(priv->phydev); @@ -390,14 +389,9 @@ static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bd) return 0; } -static void sunxi_emac_eth_halt(struct eth_device *dev) +static int _sunxi_emac_eth_recv(struct emac_eth_dev *priv, void *packet) { - /* Nothing to do here */ -} - -static int sunxi_emac_eth_recv(struct eth_device *dev) -{ - struct emac_regs *regs = (struct emac_regs *)dev->iobase; + struct emac_regs *regs = priv->regs; struct emac_rxhdr rxhdr; u32 rxcount; u32 reg_val; @@ -415,7 +409,7 @@ static int sunxi_emac_eth_recv(struct eth_device *dev) /* Had one stuck? */ rxcount = readl(®s->rx_fbc); if (!rxcount) - return 0; + return -EAGAIN; } reg_val = readl(®s->rx_io_data); @@ -431,7 +425,7 @@ static int sunxi_emac_eth_recv(struct eth_device *dev) /* Enable RX */ setbits_le32(®s->ctl, 0x1 << 2); - return 0; + return -EAGAIN; } /* A packet ready now @@ -463,22 +457,19 @@ static int sunxi_emac_eth_recv(struct eth_device *dev) if (good_packet) { if (rx_len > DMA_CPU_TRRESHOLD) { printf("Received packet is too big (len=%d)\n", rx_len); - } else { - emac_inblk_32bit((void *)®s->rx_io_data, - net_rx_packets[0], rx_len); - - /* Pass to upper layer */ - net_process_received_packet(net_rx_packets[0], rx_len); - return rx_len; + return -EMSGSIZE; } + emac_inblk_32bit((void *)®s->rx_io_data, packet, rx_len); + return rx_len; } - return 0; + return -EIO; /* Bad packet */ } -static int sunxi_emac_eth_send(struct eth_device *dev, void *packet, int len) +static int _sunxi_emac_eth_send(struct emac_eth_dev *priv, void *packet, + int len) { - struct emac_regs *regs = (struct emac_regs *)dev->iobase; + struct emac_regs *regs = priv->regs; /* Select channel 0 */ writel(0, ®s->tx_ins); @@ -495,17 +486,64 @@ static int sunxi_emac_eth_send(struct eth_device *dev, void *packet, int len) return 0; } -int sunxi_emac_initialize(void) +static void sunxi_emac_board_setup(struct emac_eth_dev *priv) { struct sunxi_ccm_reg *const ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; struct sunxi_sramc_regs *sram = (struct sunxi_sramc_regs *)SUNXI_SRAMC_BASE; + struct emac_regs *regs = priv->regs; + int pin; + + /* Map SRAM to EMAC */ + setbits_le32(&sram->ctrl1, 0x5 << 2); + + /* Configure pin mux settings for MII Ethernet */ + for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(17); pin++) + sunxi_gpio_set_cfgpin(pin, SUNXI_GPA_EMAC); + + /* Set up clock gating */ + setbits_le32(&ccm->ahb_gate0, 0x1 << AHB_GATE_OFFSET_EMAC); + + /* Set MII clock */ + clrsetbits_le32(®s->mac_mcfg, 0xf << 2, 0xd << 2); +} + +static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bis) +{ + return _sunxi_emac_eth_init(dev->priv, dev->enetaddr); +} + +static void sunxi_emac_eth_halt(struct eth_device *dev) +{ + /* Nothing to do here */ +} + +static int sunxi_emac_eth_recv(struct eth_device *dev) +{ + int rx_len; + + rx_len = _sunxi_emac_eth_recv(dev->priv, net_rx_packets[0]); + if (rx_len <= 0) + return 0; + + /* Pass to upper layer */ + net_process_received_packet(net_rx_packets[0], rx_len); + + return rx_len; +} + +static int sunxi_emac_eth_send(struct eth_device *dev, void *packet, int length) +{ + return _sunxi_emac_eth_send(dev->priv, packet, length); +} + +int sunxi_emac_initialize(void) +{ struct emac_regs *regs = (struct emac_regs *)SUNXI_EMAC_BASE; struct eth_device *dev; struct emac_eth_dev *priv; - int pin; dev = malloc(sizeof(*dev)); if (dev == NULL) @@ -520,19 +558,6 @@ int sunxi_emac_initialize(void) memset(dev, 0, sizeof(*dev)); memset(priv, 0, sizeof(struct emac_eth_dev)); - /* Map SRAM to EMAC */ - setbits_le32(&sram->ctrl1, 0x5 << 2); - - /* Configure pin mux settings for MII Ethernet */ - for (pin = SUNXI_GPA(0); pin <= SUNXI_GPA(17); pin++) - sunxi_gpio_set_cfgpin(pin, SUNXI_GPA_EMAC); - - /* Set up clock gating */ - setbits_le32(&ccm->ahb_gate0, 0x1 << AHB_GATE_OFFSET_EMAC); - - /* Set MII clock */ - clrsetbits_le32(®s->mac_mcfg, 0xf << 2, 0xd << 2); - priv->regs = regs; dev->iobase = (int)regs; dev->priv = priv; @@ -542,6 +567,8 @@ int sunxi_emac_initialize(void) dev->recv = sunxi_emac_eth_recv; strcpy(dev->name, "emac"); + sunxi_emac_board_setup(priv); + eth_register(dev); return sunxi_emac_init_phy(priv, dev); -- cgit v1.2.3 From d88c2f114970ab5153f39901324b9983d227f618 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 25 Apr 2015 13:46:28 +0200 Subject: sunxi: emac: Rename DMA_CPU_TRRESHOLD to EMAC_RX_BUFSIZE Besides being spelled wrong, the DMA_CPU_TRRESHOLD define actually has nothing to do with DMA as we only use mmio fifo access. Rename it to EMAC_RX_BUFSIZE to properly reflect what it does. Signed-off-by: Hans de Goede Reviewed-by: Simon Glass Acked-by: Ian Campbell Reviewed-by: Stefan Roese --- drivers/net/sunxi_emac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c index 038f474d25..e43b1e7d64 100644 --- a/drivers/net/sunxi_emac.c +++ b/drivers/net/sunxi_emac.c @@ -153,7 +153,7 @@ struct sunxi_sramc_regs { #define EMAC_CRCERR (0x1 << 4) #define EMAC_LENERR (0x3 << 5) -#define DMA_CPU_TRRESHOLD 2000 +#define EMAC_RX_BUFSIZE 2000 struct emac_eth_dev { struct emac_regs *regs; @@ -455,7 +455,7 @@ static int _sunxi_emac_eth_recv(struct emac_eth_dev *priv, void *packet) /* Move data from EMAC */ if (good_packet) { - if (rx_len > DMA_CPU_TRRESHOLD) { + if (rx_len > EMAC_RX_BUFSIZE) { printf("Received packet is too big (len=%d)\n", rx_len); return -EMSGSIZE; } -- cgit v1.2.3 From 939ed1cba84cefedfbaeed2690c05bb9360d9b88 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 19 Apr 2015 11:48:19 +0200 Subject: sunxi: emac: Add driver model support Modify the sunxi-emac eth driver to support driver model. Signed-off-by: Hans de Goede Acked-by: Ian Campbell Reviewed-by: Stefan Roese --- drivers/net/sunxi_emac.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) (limited to 'drivers') diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c index e43b1e7d64..306a022c2f 100644 --- a/drivers/net/sunxi_emac.c +++ b/drivers/net/sunxi_emac.c @@ -7,6 +7,7 @@ */ #include +#include #include #include #include @@ -160,6 +161,9 @@ struct emac_eth_dev { struct mii_dev *bus; struct phy_device *phydev; int link_printed; +#ifdef CONFIG_DM_ETH + uchar rx_buf[EMAC_RX_BUFSIZE]; +#endif }; struct emac_rxhdr { @@ -509,6 +513,7 @@ static void sunxi_emac_board_setup(struct emac_eth_dev *priv) clrsetbits_le32(®s->mac_mcfg, 0xf << 2, 0xd << 2); } +#ifndef CONFIG_DM_ETH static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bis) { return _sunxi_emac_eth_init(dev->priv, dev->enetaddr); @@ -573,3 +578,79 @@ int sunxi_emac_initialize(void) return sunxi_emac_init_phy(priv, dev); } +#endif + +#ifdef CONFIG_DM_ETH +static int sunxi_emac_eth_start(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + + return _sunxi_emac_eth_init(dev->priv, pdata->enetaddr); +} + +static int sunxi_emac_eth_send(struct udevice *dev, void *packet, int length) +{ + struct emac_eth_dev *priv = dev_get_priv(dev); + + return _sunxi_emac_eth_send(priv, packet, length); +} + +static int sunxi_emac_eth_recv(struct udevice *dev, uchar **packetp) +{ + struct emac_eth_dev *priv = dev_get_priv(dev); + int rx_len; + + rx_len = _sunxi_emac_eth_recv(priv, priv->rx_buf); + *packetp = priv->rx_buf; + + return rx_len; +} + +static void sunxi_emac_eth_stop(struct udevice *dev) +{ + /* Nothing to do here */ +} + +static int sunxi_emac_eth_probe(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + struct emac_eth_dev *priv = dev_get_priv(dev); + + priv->regs = (struct emac_regs *)pdata->iobase; + sunxi_emac_board_setup(priv); + + return sunxi_emac_init_phy(priv, dev); +} + +static const struct eth_ops sunxi_emac_eth_ops = { + .start = sunxi_emac_eth_start, + .send = sunxi_emac_eth_send, + .recv = sunxi_emac_eth_recv, + .stop = sunxi_emac_eth_stop, +}; + +static int sunxi_emac_eth_ofdata_to_platdata(struct udevice *dev) +{ + struct eth_pdata *pdata = dev_get_platdata(dev); + + pdata->iobase = dev_get_addr(dev); + + return 0; +} + +static const struct udevice_id sunxi_emac_eth_ids[] = { + { .compatible = "allwinner,sun4i-a10-emac" }, + { } +}; + +U_BOOT_DRIVER(eth_sunxi_emac) = { + .name = "eth_sunxi_emac", + .id = UCLASS_ETH, + .of_match = sunxi_emac_eth_ids, + .ofdata_to_platdata = sunxi_emac_eth_ofdata_to_platdata, + .probe = sunxi_emac_eth_probe, + .ops = &sunxi_emac_eth_ops, + .priv_auto_alloc_size = sizeof(struct emac_eth_dev), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), +}; +#endif -- cgit v1.2.3 From d17e1577a203e486d8a15bfa015a6410d99079de Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 23 Apr 2015 18:47:47 +0200 Subject: sunxi: emac: Remove non driver-model code All sunxi boards now use the driver-model, so remove the non driver-model code. Signed-off-by: Hans de Goede Reviewed-by: Simon Glass Acked-by: Ian Campbell --- drivers/net/sunxi_emac.c | 69 ------------------------------------------------ 1 file changed, 69 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sunxi_emac.c b/drivers/net/sunxi_emac.c index 306a022c2f..e939bf2108 100644 --- a/drivers/net/sunxi_emac.c +++ b/drivers/net/sunxi_emac.c @@ -513,74 +513,6 @@ static void sunxi_emac_board_setup(struct emac_eth_dev *priv) clrsetbits_le32(®s->mac_mcfg, 0xf << 2, 0xd << 2); } -#ifndef CONFIG_DM_ETH -static int sunxi_emac_eth_init(struct eth_device *dev, bd_t *bis) -{ - return _sunxi_emac_eth_init(dev->priv, dev->enetaddr); -} - -static void sunxi_emac_eth_halt(struct eth_device *dev) -{ - /* Nothing to do here */ -} - -static int sunxi_emac_eth_recv(struct eth_device *dev) -{ - int rx_len; - - rx_len = _sunxi_emac_eth_recv(dev->priv, net_rx_packets[0]); - if (rx_len <= 0) - return 0; - - /* Pass to upper layer */ - net_process_received_packet(net_rx_packets[0], rx_len); - - return rx_len; -} - -static int sunxi_emac_eth_send(struct eth_device *dev, void *packet, int length) -{ - return _sunxi_emac_eth_send(dev->priv, packet, length); -} - -int sunxi_emac_initialize(void) -{ - struct emac_regs *regs = - (struct emac_regs *)SUNXI_EMAC_BASE; - struct eth_device *dev; - struct emac_eth_dev *priv; - - dev = malloc(sizeof(*dev)); - if (dev == NULL) - return -ENOMEM; - - priv = (struct emac_eth_dev *)malloc(sizeof(struct emac_eth_dev)); - if (!priv) { - free(dev); - return -ENOMEM; - } - - memset(dev, 0, sizeof(*dev)); - memset(priv, 0, sizeof(struct emac_eth_dev)); - - priv->regs = regs; - dev->iobase = (int)regs; - dev->priv = priv; - dev->init = sunxi_emac_eth_init; - dev->halt = sunxi_emac_eth_halt; - dev->send = sunxi_emac_eth_send; - dev->recv = sunxi_emac_eth_recv; - strcpy(dev->name, "emac"); - - sunxi_emac_board_setup(priv); - - eth_register(dev); - - return sunxi_emac_init_phy(priv, dev); -} -#endif - -#ifdef CONFIG_DM_ETH static int sunxi_emac_eth_start(struct udevice *dev) { struct eth_pdata *pdata = dev_get_platdata(dev); @@ -653,4 +585,3 @@ U_BOOT_DRIVER(eth_sunxi_emac) = { .priv_auto_alloc_size = sizeof(struct emac_eth_dev), .platdata_auto_alloc_size = sizeof(struct eth_pdata), }; -#endif -- cgit v1.2.3 From 421b32b8808a4d3dc59e84c69fc23b5d62302272 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 26 Apr 2015 11:19:37 +0200 Subject: sunxi: axp: Remove non driver-model support from the axp gpio code Now that all sunxi boards are using driver-model for gpio (*), we can remove the non driver-model support from the axp gpio code, and the glue to call into the axp gpio code from the sunxi_gpio non driver-model code. *) For the regular u-boot build, SPL still uses non driver-model gpio for now, but the SPL never uses axp gpios support and we were already not building axp-gpio support for the SPL. Signed-off-by: Hans de Goede Reviewed-by: Simon Glass Acked-by: Ian Campbell --- drivers/gpio/axp_gpio.c | 17 ++++++++--------- drivers/gpio/sunxi_gpio.c | 32 -------------------------------- 2 files changed, 8 insertions(+), 41 deletions(-) (limited to 'drivers') diff --git a/drivers/gpio/axp_gpio.c b/drivers/gpio/axp_gpio.c index 55f20a34b6..2e97cc39d6 100644 --- a/drivers/gpio/axp_gpio.c +++ b/drivers/gpio/axp_gpio.c @@ -26,6 +26,8 @@ #error Unknown AXP model #endif +static int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val); + static u8 axp_get_gpio_ctrl_reg(unsigned pin) { switch (pin) { @@ -41,7 +43,7 @@ static u8 axp_get_gpio_ctrl_reg(unsigned pin) return 0; } -int axp_gpio_direction_input(struct udevice *dev, unsigned pin) +static int axp_gpio_direction_input(struct udevice *dev, unsigned pin) { u8 reg; @@ -59,7 +61,8 @@ int axp_gpio_direction_input(struct udevice *dev, unsigned pin) } } -int axp_gpio_direction_output(struct udevice *dev, unsigned pin, int val) +static int axp_gpio_direction_output(struct udevice *dev, unsigned pin, + int val) { __maybe_unused int ret; u8 reg; @@ -84,7 +87,7 @@ int axp_gpio_direction_output(struct udevice *dev, unsigned pin, int val) } } -int axp_gpio_get_value(struct udevice *dev, unsigned pin) +static int axp_gpio_get_value(struct udevice *dev, unsigned pin) { u8 reg, val, mask; int ret; @@ -116,7 +119,7 @@ int axp_gpio_get_value(struct udevice *dev, unsigned pin) return (val & mask) ? 1 : 0; } -int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val) +static int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val) { u8 reg; @@ -140,7 +143,6 @@ int axp_gpio_set_value(struct udevice *dev, unsigned pin, int val) } } -#ifdef CONFIG_DM_GPIO static const struct dm_gpio_ops gpio_axp_ops = { .direction_input = axp_gpio_direction_input, .direction_output = axp_gpio_direction_output, @@ -165,23 +167,20 @@ U_BOOT_DRIVER(gpio_axp) = { .ops = &gpio_axp_ops, .probe = gpio_axp_probe, }; -#endif int axp_gpio_init(void) { - __maybe_unused struct udevice *dev; + struct udevice *dev; int ret; ret = pmic_bus_init(); if (ret) return ret; -#ifdef CONFIG_DM_GPIO /* There is no devicetree support for the axp yet, so bind directly */ ret = device_bind_driver(dm_root(), "gpio_axp", "AXP-gpio", &dev); if (ret) return ret; -#endif return 0; } diff --git a/drivers/gpio/sunxi_gpio.c b/drivers/gpio/sunxi_gpio.c index 21c3ff1e75..f9881308f4 100644 --- a/drivers/gpio/sunxi_gpio.c +++ b/drivers/gpio/sunxi_gpio.c @@ -74,10 +74,6 @@ int gpio_free(unsigned gpio) int gpio_direction_input(unsigned gpio) { -#if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO - if (gpio >= SUNXI_GPIO_AXP0_START) - return axp_gpio_direction_input(NULL, gpio - SUNXI_GPIO_AXP0_START); -#endif sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_INPUT); return 0; @@ -85,11 +81,6 @@ int gpio_direction_input(unsigned gpio) int gpio_direction_output(unsigned gpio, int value) { -#if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO - if (gpio >= SUNXI_GPIO_AXP0_START) - return axp_gpio_direction_output(NULL, gpio - SUNXI_GPIO_AXP0_START, - value); -#endif sunxi_gpio_set_cfgpin(gpio, SUNXI_GPIO_OUTPUT); return sunxi_gpio_output(gpio, value); @@ -97,19 +88,11 @@ int gpio_direction_output(unsigned gpio, int value) int gpio_get_value(unsigned gpio) { -#if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO - if (gpio >= SUNXI_GPIO_AXP0_START) - return axp_gpio_get_value(NULL, gpio - SUNXI_GPIO_AXP0_START); -#endif return sunxi_gpio_input(gpio); } int gpio_set_value(unsigned gpio, int value) { -#if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO - if (gpio >= SUNXI_GPIO_AXP0_START) - return axp_gpio_set_value(NULL, gpio - SUNXI_GPIO_AXP0_START, value); -#endif return sunxi_gpio_output(gpio, value); } @@ -120,21 +103,6 @@ int sunxi_name_to_gpio(const char *name) long pin; char *eptr; -#if !defined CONFIG_SPL_BUILD && defined CONFIG_AXP_GPIO - if (strncasecmp(name, "AXP0-", 5) == 0) { - name += 5; - if (strcmp(name, "VBUS-DETECT") == 0) - return SUNXI_GPIO_AXP0_START + - SUNXI_GPIO_AXP0_VBUS_DETECT; - if (strcmp(name, "VBUS-ENABLE") == 0) - return SUNXI_GPIO_AXP0_START + - SUNXI_GPIO_AXP0_VBUS_ENABLE; - pin = simple_strtol(name, &eptr, 10); - if (!*name || *eptr) - return -1; - return SUNXI_GPIO_AXP0_START + pin; - } -#endif if (*name == 'P' || *name == 'p') name++; if (*name >= 'A') { -- cgit v1.2.3 From 375de01702f4b0b1a27715ca1a18110d6dbfdebe Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 27 Apr 2015 11:44:22 +0200 Subject: sunxi: usb: Move setup of host controller clocks to the host controller drivers The sunxi "usbc" code is mostly about phy setup, but currently also sets up the host controller clocks, which is something which really belongs in the host controller drivers, so move it there. This is a preparation patch for moving the sunxi ehci code to the driver model and for adding ohci support. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- drivers/usb/host/ehci-sunxi.c | 24 ++++++++++++++++++++++-- drivers/usb/musb-new/sunxi.c | 20 ++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c index eda9f698d9..41e4d7f908 100644 --- a/drivers/usb/host/ehci-sunxi.c +++ b/drivers/usb/host/ehci-sunxi.c @@ -9,19 +9,29 @@ * SPDX-License-Identifier: GPL-2.0+ */ -#include #include +#include +#include +#include #include "ehci.h" int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, struct ehci_hcor **hcor) { - int err; + struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + int ahb_gate_offset, err; err = sunxi_usbc_request_resources(index + 1); if (err) return err; + ahb_gate_offset = index ? AHB_GATE_OFFSET_USB_EHCI1 : + AHB_GATE_OFFSET_USB_EHCI0; + setbits_le32(&ccm->ahb_gate0, 1 << ahb_gate_offset); +#ifdef CONFIG_SUNXI_GEN_SUN6I + setbits_le32(&ccm->ahb_reset0_cfg, 1 << ahb_gate_offset); +#endif + sunxi_usbc_enable(index + 1); sunxi_usbc_vbus_enable(index + 1); @@ -39,8 +49,18 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, int ehci_hcd_stop(int index) { + struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + int ahb_gate_offset; + sunxi_usbc_vbus_disable(index + 1); sunxi_usbc_disable(index + 1); + ahb_gate_offset = index ? AHB_GATE_OFFSET_USB_EHCI1 : + AHB_GATE_OFFSET_USB_EHCI0; +#ifdef CONFIG_SUNXI_GEN_SUN6I + clrbits_le32(&ccm->ahb_reset0_cfg, 1 << ahb_gate_offset); +#endif + clrbits_le32(&ccm->ahb_gate0, 1 << ahb_gate_offset); + return sunxi_usbc_free_resources(index + 1); } diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index c9a6a16b89..e3c6d6a98b 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -22,6 +22,7 @@ */ #include #include +#include #include #include #include @@ -219,11 +220,24 @@ static void sunxi_musb_enable(struct musb *musb) static void sunxi_musb_disable(struct musb *musb) { + struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; + pr_debug("%s():\n", __func__); /* Put the controller back in a pristane state for "usb reset" */ if (musb->is_active) { sunxi_usbc_disable(0); +#ifdef CONFIG_SUNXI_GEN_SUN6I + clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); +#endif + clrbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0); + + mdelay(10); + + setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0); +#ifdef CONFIG_SUNXI_GEN_SUN6I + setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); +#endif sunxi_usbc_enable(0); musb->is_active = 0; } @@ -231,6 +245,7 @@ static void sunxi_musb_disable(struct musb *musb) static int sunxi_musb_init(struct musb *musb) { + struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; int err; pr_debug("%s():\n", __func__); @@ -249,6 +264,11 @@ static int sunxi_musb_init(struct musb *musb) } musb->isr = sunxi_musb_interrupt; + + setbits_le32(&ccm->ahb_gate0, 1 << AHB_GATE_OFFSET_USB0); +#ifdef CONFIG_SUNXI_GEN_SUN6I + setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); +#endif sunxi_usbc_enable(0); USBC_ConfigFIFO_Base(); -- cgit v1.2.3 From a781c97aaa1712449968d41ae30dc673877058ab Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 27 Apr 2015 14:36:23 +0200 Subject: sunxi: usb: Remove sunxi_usbc_get_io_base function This is the only function left in sunxi/usbc.c which is not phy related, so remove it. This is a preparation patch for turning the usbc.c code into a proper usb phy driver. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- drivers/usb/host/ehci-sunxi.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c index 41e4d7f908..5de20f9d2c 100644 --- a/drivers/usb/host/ehci-sunxi.c +++ b/drivers/usb/host/ehci-sunxi.c @@ -35,7 +35,10 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, sunxi_usbc_enable(index + 1); sunxi_usbc_vbus_enable(index + 1); - *hccr = sunxi_usbc_get_io_base(index + 1); + if (index == 0) + *hccr = (void *)SUNXI_USB1_BASE; + else + *hccr = (void *)SUNXI_USB2_BASE; *hcor = (struct ehci_hcor *)((uint32_t) *hccr + HC_LENGTH(ehci_readl(&(*hccr)->cr_capbase))); -- cgit v1.2.3 From 7b798658b289aa4466d974320e2b69f4287216f7 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 27 Apr 2015 14:54:47 +0200 Subject: sunxi: usb: Rename sunxi_usbc_foo functions to sunxi_usb_phy_bar Rename the sunxi_usbc_foo functions to sunxi_usb_phy_bar to make it clear that these are usb-phy functions. Also change the verbs & nouns in the suffix to match the verbs & nouns used in the Linux kernels generic phy framework. This patch purely renames things, it contains no functional changes. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- drivers/usb/host/ehci-sunxi.c | 17 +++++++++-------- drivers/usb/musb-new/musb_uboot.c | 4 ++-- drivers/usb/musb-new/sunxi.c | 20 ++++++++++---------- 3 files changed, 21 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c index 5de20f9d2c..b6fa538fb2 100644 --- a/drivers/usb/host/ehci-sunxi.c +++ b/drivers/usb/host/ehci-sunxi.c @@ -1,7 +1,8 @@ /* - * Copyright (C) 2014 Roman Byshko + * Sunxi ehci glue * - * Roman Byshko + * Copyright (C) 2015 Hans de Goede + * Copyright (C) 2014 Roman Byshko * * Based on code from * Allwinner Technology Co., Ltd. @@ -21,7 +22,7 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; int ahb_gate_offset, err; - err = sunxi_usbc_request_resources(index + 1); + err = sunxi_usb_phy_probe(index + 1); if (err) return err; @@ -32,8 +33,8 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, setbits_le32(&ccm->ahb_reset0_cfg, 1 << ahb_gate_offset); #endif - sunxi_usbc_enable(index + 1); - sunxi_usbc_vbus_enable(index + 1); + sunxi_usb_phy_init(index + 1); + sunxi_usb_phy_power_on(index + 1); if (index == 0) *hccr = (void *)SUNXI_USB1_BASE; @@ -55,8 +56,8 @@ int ehci_hcd_stop(int index) struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; int ahb_gate_offset; - sunxi_usbc_vbus_disable(index + 1); - sunxi_usbc_disable(index + 1); + sunxi_usb_phy_power_off(index + 1); + sunxi_usb_phy_exit(index + 1); ahb_gate_offset = index ? AHB_GATE_OFFSET_USB_EHCI1 : AHB_GATE_OFFSET_USB_EHCI0; @@ -65,5 +66,5 @@ int ehci_hcd_stop(int index) #endif clrbits_le32(&ccm->ahb_gate0, 1 << ahb_gate_offset); - return sunxi_usbc_free_resources(index + 1); + return sunxi_usb_phy_remove(index + 1); } diff --git a/drivers/usb/musb-new/musb_uboot.c b/drivers/usb/musb-new/musb_uboot.c index 7d90ebc1f5..4d0213a52b 100644 --- a/drivers/usb/musb-new/musb_uboot.c +++ b/drivers/usb/musb-new/musb_uboot.c @@ -195,12 +195,12 @@ int usb_reset_root_port(void) * when clearing reset on low-speed devices, temporary disable * squelch detection to work around this. */ - sunxi_usbc_enable_squelch_detect(0, 0); + sunxi_usb_phy_enable_squelch_detect(0, 0); #endif power = musb_readb(mbase, MUSB_POWER); musb_writeb(mbase, MUSB_POWER, ~MUSB_POWER_RESET & power); #ifdef CONFIG_ARCH_SUNXI - sunxi_usbc_enable_squelch_detect(0, 1); + sunxi_usb_phy_enable_squelch_detect(0, 1); #endif host->isr(0, host); host_speed = (musb_readb(mbase, MUSB_POWER) & MUSB_POWER_HSMODE) ? diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index e3c6d6a98b..5a9d39ca12 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -214,7 +214,7 @@ static void sunxi_musb_enable(struct musb *musb) if (is_host_enabled(musb)) { /* port power on */ - sunxi_usbc_vbus_enable(0); + sunxi_usb_phy_power_on(0); } } @@ -226,7 +226,7 @@ static void sunxi_musb_disable(struct musb *musb) /* Put the controller back in a pristane state for "usb reset" */ if (musb->is_active) { - sunxi_usbc_disable(0); + sunxi_usb_phy_exit(0); #ifdef CONFIG_SUNXI_GEN_SUN6I clrbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); #endif @@ -238,7 +238,7 @@ static void sunxi_musb_disable(struct musb *musb) #ifdef CONFIG_SUNXI_GEN_SUN6I setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); #endif - sunxi_usbc_enable(0); + sunxi_usb_phy_init(0); musb->is_active = 0; } } @@ -250,15 +250,15 @@ static int sunxi_musb_init(struct musb *musb) pr_debug("%s():\n", __func__); - err = sunxi_usbc_request_resources(0); + err = sunxi_usb_phy_probe(0); if (err) return err; if (is_host_enabled(musb)) { - err = sunxi_usbc_vbus_detect(0); + err = sunxi_usb_phy_vbus_detect(0); if (err) { eprintf("Error: A charger is plugged into the OTG\n"); - sunxi_usbc_free_resources(0); + sunxi_usb_phy_remove(0); return -EIO; } } @@ -269,7 +269,7 @@ static int sunxi_musb_init(struct musb *musb) #ifdef CONFIG_SUNXI_GEN_SUN6I setbits_le32(&ccm->ahb_reset0_cfg, 1 << AHB_GATE_OFFSET_USB0); #endif - sunxi_usbc_enable(0); + sunxi_usb_phy_init(0); USBC_ConfigFIFO_Base(); USBC_EnableDpDmPullUp(musb->mregs); @@ -293,10 +293,10 @@ static int sunxi_musb_exit(struct musb *musb) USBC_DisableDpDmPullUp(musb->mregs); USBC_DisableIdPullUp(musb->mregs); - sunxi_usbc_vbus_disable(0); - sunxi_usbc_disable(0); + sunxi_usb_phy_power_off(0); + sunxi_usb_phy_exit(0); - return sunxi_usbc_free_resources(0); + return sunxi_usb_phy_remove(0); } const struct musb_platform_ops sunxi_musb_ops = { -- cgit v1.2.3 From 2aacc4239c32aa732621f3a432d576c68c3016d8 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 27 Apr 2015 15:05:10 +0200 Subject: sunxi: usb: Rename the usbc.? files to usb_phy.? The usbc.? files now only contain usb-phy related code, rename them to make this clear. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- drivers/usb/host/ehci-sunxi.c | 2 +- drivers/usb/musb-new/musb_uboot.c | 2 +- drivers/usb/musb-new/sunxi.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c index b6fa538fb2..9e74a0babf 100644 --- a/drivers/usb/host/ehci-sunxi.c +++ b/drivers/usb/host/ehci-sunxi.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include #include "ehci.h" diff --git a/drivers/usb/musb-new/musb_uboot.c b/drivers/usb/musb-new/musb_uboot.c index 4d0213a52b..d1ee5f8d06 100644 --- a/drivers/usb/musb-new/musb_uboot.c +++ b/drivers/usb/musb-new/musb_uboot.c @@ -1,7 +1,7 @@ #include #include #ifdef CONFIG_ARCH_SUNXI -#include +#include #endif #include #include diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index 5a9d39ca12..4f08f9f906 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include "linux-compat.h" #include "musb_core.h" -- cgit v1.2.3 From e13afeef6f5d3c9c4fc130b21ee7c885f96d55f2 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 27 Apr 2015 16:50:04 +0200 Subject: sunxi: usb: Do not call phy_probe from hcd code The 2/3 usb-phys on the sunxi SoCs are really a single separate functional block, and are modelled as such in devicetree. So once we've moved all the sunxi usb code to the driver-model then phy_probe will be called once for the entire block from the driver-model enumeration code. Move to this now as this also avoids problems with phy_probe being called multiple times once we introduce ohci support. This also allows us to get rid of the sunxi_usb_phy_enabled_count variable as phy_probe now is guaranteed to be called only once. Since we're effectively rewriting the probe / remove functions, move them to the end of the file while we are at it, as that is the most logical place for them. Signed-off-by: Hans de Goede Acked-by: Ian Campbell --- drivers/usb/host/ehci-sunxi.c | 8 ++------ drivers/usb/musb-new/sunxi.c | 7 +------ 2 files changed, 3 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-sunxi.c b/drivers/usb/host/ehci-sunxi.c index 9e74a0babf..0edb6438cb 100644 --- a/drivers/usb/host/ehci-sunxi.c +++ b/drivers/usb/host/ehci-sunxi.c @@ -20,11 +20,7 @@ int ehci_hcd_init(int index, enum usb_init_type init, struct ehci_hccr **hccr, struct ehci_hcor **hcor) { struct sunxi_ccm_reg *ccm = (struct sunxi_ccm_reg *)SUNXI_CCM_BASE; - int ahb_gate_offset, err; - - err = sunxi_usb_phy_probe(index + 1); - if (err) - return err; + int ahb_gate_offset; ahb_gate_offset = index ? AHB_GATE_OFFSET_USB_EHCI1 : AHB_GATE_OFFSET_USB_EHCI0; @@ -66,5 +62,5 @@ int ehci_hcd_stop(int index) #endif clrbits_le32(&ccm->ahb_gate0, 1 << ahb_gate_offset); - return sunxi_usb_phy_remove(index + 1); + return 0; } diff --git a/drivers/usb/musb-new/sunxi.c b/drivers/usb/musb-new/sunxi.c index 4f08f9f906..e8a3a23aa4 100644 --- a/drivers/usb/musb-new/sunxi.c +++ b/drivers/usb/musb-new/sunxi.c @@ -250,15 +250,10 @@ static int sunxi_musb_init(struct musb *musb) pr_debug("%s():\n", __func__); - err = sunxi_usb_phy_probe(0); - if (err) - return err; - if (is_host_enabled(musb)) { err = sunxi_usb_phy_vbus_detect(0); if (err) { eprintf("Error: A charger is plugged into the OTG\n"); - sunxi_usb_phy_remove(0); return -EIO; } } @@ -296,7 +291,7 @@ static int sunxi_musb_exit(struct musb *musb) sunxi_usb_phy_power_off(0); sunxi_usb_phy_exit(0); - return sunxi_usb_phy_remove(0); + return 0; } const struct musb_platform_ops sunxi_musb_ops = { -- cgit v1.2.3