diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/i2c/omap24xx_i2c.c | 1 | ||||
-rw-r--r-- | drivers/mmc/bcm2835_sdhci.c | 81 | ||||
-rw-r--r-- | drivers/mmc/omap_hsmmc.c | 35 | ||||
-rw-r--r-- | drivers/power/Kconfig | 7 | ||||
-rw-r--r-- | drivers/power/twl4030.c | 9 | ||||
-rw-r--r-- | drivers/usb/eth/smsc95xx.c | 4 | ||||
-rw-r--r-- | drivers/video/bcm2835.c | 140 | ||||
-rw-r--r-- | drivers/watchdog/Kconfig | 12 | ||||
-rw-r--r-- | drivers/watchdog/Makefile | 1 | ||||
-rw-r--r-- | drivers/watchdog/bcm2835_wdt.c | 35 |
10 files changed, 199 insertions, 126 deletions
diff --git a/drivers/i2c/omap24xx_i2c.c b/drivers/i2c/omap24xx_i2c.c index 26996e9..a23737a 100644 --- a/drivers/i2c/omap24xx_i2c.c +++ b/drivers/i2c/omap24xx_i2c.c @@ -910,6 +910,7 @@ static const struct dm_i2c_ops omap_i2c_ops = { }; static const struct udevice_id omap_i2c_ids[] = { + { .compatible = "ti,omap3-i2c" }, { .compatible = "ti,omap4-i2c" }, { } }; diff --git a/drivers/mmc/bcm2835_sdhci.c b/drivers/mmc/bcm2835_sdhci.c index 20079bc..b6e2fc6 100644 --- a/drivers/mmc/bcm2835_sdhci.c +++ b/drivers/mmc/bcm2835_sdhci.c @@ -37,15 +37,24 @@ */ #include <common.h> +#include <dm.h> #include <malloc.h> +#include <memalign.h> #include <sdhci.h> -#include <mach/timer.h> +#include <asm/arch/msg.h> +#include <asm/arch/mbox.h> #include <mach/sdhci.h> +#include <mach/timer.h> /* 400KHz is max freq for card ID etc. Use that as min */ #define MIN_FREQ 400000 #define SDHCI_BUFFER 0x20 +struct bcm2835_sdhci_plat { + struct mmc_config cfg; + struct mmc mmc; +}; + struct bcm2835_sdhci_host { struct sdhci_host host; uint twoticks_delay; @@ -58,7 +67,7 @@ static inline struct bcm2835_sdhci_host *to_bcm(struct sdhci_host *host) } static inline void bcm2835_sdhci_raw_writel(struct sdhci_host *host, u32 val, - int reg) + int reg) { struct bcm2835_sdhci_host *bcm_host = to_bcm(host); @@ -153,16 +162,33 @@ static const struct sdhci_ops bcm2835_ops = { .read_b = bcm2835_sdhci_readb, }; -int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq) +static int bcm2835_sdhci_bind(struct udevice *dev) { - struct bcm2835_sdhci_host *bcm_host; - struct sdhci_host *host; + struct bcm2835_sdhci_plat *plat = dev_get_platdata(dev); - bcm_host = calloc(1, sizeof(*bcm_host)); - if (!bcm_host) { - printf("sdhci_host calloc fail!\n"); - return -ENOMEM; + return sdhci_bind(dev, &plat->mmc, &plat->cfg); +} + +static int bcm2835_sdhci_probe(struct udevice *dev) +{ + struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev); + struct bcm2835_sdhci_plat *plat = dev_get_platdata(dev); + struct bcm2835_sdhci_host *priv = dev_get_priv(dev); + struct sdhci_host *host = &priv->host; + fdt_addr_t base; + int emmc_freq; + int ret; + + base = dev_get_addr(dev); + if (base == FDT_ADDR_T_NONE) + return -EINVAL; + + ret = bcm2835_get_mmc_clock(); + if (ret < 0) { + debug("%s: Failed to set MMC clock (err=%d)\n", __func__, ret); + return ret; } + emmc_freq = ret; /* * See the comments in bcm2835_sdhci_raw_writel(). @@ -177,19 +203,42 @@ int bcm2835_sdhci_init(u32 regbase, u32 emmc_freq) * Multiply by 1000000 to get uS per two ticks. * +1 for hack rounding. */ - bcm_host->twoticks_delay = ((2 * 1000000) / MIN_FREQ) + 1; - bcm_host->last_write = 0; + priv->twoticks_delay = ((2 * 1000000) / MIN_FREQ) + 1; + priv->last_write = 0; - host = &bcm_host->host; - host->name = "bcm2835_sdhci"; - host->ioaddr = (void *)(unsigned long)regbase; + host->name = dev->name; + host->ioaddr = (void *)base; host->quirks = SDHCI_QUIRK_BROKEN_VOLTAGE | SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_NO_HISPD_BIT; host->max_clk = emmc_freq; host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; host->ops = &bcm2835_ops; - add_sdhci(host, 0, MIN_FREQ); + ret = sdhci_setup_cfg(&plat->cfg, host, emmc_freq, MIN_FREQ); + if (ret) { + debug("%s: Failed to setup SDHCI (err=%d)\n", __func__, ret); + return ret; + } + + upriv->mmc = &plat->mmc; + host->mmc = &plat->mmc; + host->mmc->priv = host; - return 0; + return sdhci_probe(dev); } + +static const struct udevice_id bcm2835_sdhci_match[] = { + { .compatible = "brcm,bcm2835-sdhci" }, + { /* sentinel */ } +}; + +U_BOOT_DRIVER(sdhci_cdns) = { + .name = "sdhci-bcm2835", + .id = UCLASS_MMC, + .of_match = bcm2835_sdhci_match, + .bind = bcm2835_sdhci_bind, + .probe = bcm2835_sdhci_probe, + .priv_auto_alloc_size = sizeof(struct bcm2835_sdhci_host), + .platdata_auto_alloc_size = sizeof(struct bcm2835_sdhci_plat), + .ops = &sdhci_ops, +}; diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index 83dda09..d151fe7 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -61,6 +61,10 @@ struct omap_hsmmc_plat { struct mmc mmc; }; +struct omap2_mmc_platform_config { + u32 reg_offset; +}; + struct omap_hsmmc_data { struct hsmmc *base_addr; #ifndef CONFIG_DM_MMC @@ -778,12 +782,14 @@ static int omap_hsmmc_ofdata_to_platdata(struct udevice *dev) struct omap_hsmmc_data *priv = dev_get_priv(dev); struct omap_hsmmc_plat *plat = dev_get_platdata(dev); struct mmc_config *cfg = &plat->cfg; + struct omap2_mmc_platform_config *data = + (struct omap2_mmc_platform_config *)dev_get_driver_data(dev); const void *fdt = gd->fdt_blob; int node = dev_of_offset(dev); int val; priv->base_addr = map_physmem(dev_get_addr(dev), sizeof(struct hsmmc *), - MAP_NOCACHE); + MAP_NOCACHE) + data->reg_offset; cfg->host_caps = MMC_MODE_HS_52MHz | MMC_MODE_HS; val = fdtdec_get_int(fdt, node, "bus-width", -1); @@ -854,10 +860,31 @@ static int omap_hsmmc_probe(struct udevice *dev) return 0; } +static const struct omap2_mmc_platform_config omap3_mmc_pdata = { + .reg_offset = 0, +}; + +static const struct omap2_mmc_platform_config am33xx_mmc_pdata = { + .reg_offset = 0x100, +}; + +static const struct omap2_mmc_platform_config omap4_mmc_pdata = { + .reg_offset = 0x100, +}; + static const struct udevice_id omap_hsmmc_ids[] = { - { .compatible = "ti,omap3-hsmmc" }, - { .compatible = "ti,omap4-hsmmc" }, - { .compatible = "ti,am33xx-hsmmc" }, + { + .compatible = "ti,omap3-hsmmc", + .data = (ulong)&omap3_mmc_pdata + }, + { + .compatible = "ti,omap4-hsmmc", + .data = (ulong)&omap4_mmc_pdata + }, + { + .compatible = "ti,am33xx-hsmmc", + .data = (ulong)&am33xx_mmc_pdata + }, { } }; diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig index 911ecb1..a7d56e6 100644 --- a/drivers/power/Kconfig +++ b/drivers/power/Kconfig @@ -308,4 +308,11 @@ config SY8106A_VOUT1_VOLT is typically used to power the VDD-CPU and should be 1200mV. Values can range from 680mV till 1950mV. +config TWL4030_POWER + depends on OMAP34XX + bool "Enable driver for TI TWL4030 power management chip" + ---help--- + The TWL4030 in a combination audio CODEC/power management with + GPIO and it is commonly used with the OMAP3 family of processors + endmenu diff --git a/drivers/power/twl4030.c b/drivers/power/twl4030.c index 8866bf1..ab98d68 100644 --- a/drivers/power/twl4030.c +++ b/drivers/power/twl4030.c @@ -171,3 +171,12 @@ void twl4030_power_mmc_init(int dev_index) mdelay(100); /* ramp-up delay from Linux code */ } } + +#ifdef CONFIG_CMD_POWEROFF +int do_poweroff(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + twl4030_power_off(); + + return 0; +} +#endif diff --git a/drivers/usb/eth/smsc95xx.c b/drivers/usb/eth/smsc95xx.c index d4c8ea4..26000a5 100644 --- a/drivers/usb/eth/smsc95xx.c +++ b/drivers/usb/eth/smsc95xx.c @@ -998,7 +998,7 @@ int smsc95xx_eth_recv(struct udevice *dev, int flags, uchar **packetp) } *packetp = ptr + sizeof(packet_len); - return packet_len; + return packet_len - 4; err: usb_ether_advance_rxbuf(ueth, -1); @@ -1009,7 +1009,7 @@ static int smsc95xx_free_pkt(struct udevice *dev, uchar *packet, int packet_len) { struct smsc95xx_private *priv = dev_get_priv(dev); - packet_len = ALIGN(packet_len, 4); + packet_len = ALIGN(packet_len + sizeof(u32), 4); usb_ether_advance_rxbuf(&priv->ueth, sizeof(u32) + packet_len); return 0; diff --git a/drivers/video/bcm2835.c b/drivers/video/bcm2835.c index cc6454f..952ef59 100644 --- a/drivers/video/bcm2835.c +++ b/drivers/video/bcm2835.c @@ -5,124 +5,56 @@ */ #include <common.h> -#include <lcd.h> -#include <memalign.h> -#include <phys2bus.h> +#include <dm.h> +#include <video.h> #include <asm/arch/mbox.h> -#include <asm/global_data.h> +#include <asm/arch/msg.h> -DECLARE_GLOBAL_DATA_PTR; - -/* Global variables that lcd.c expects to exist */ -vidinfo_t panel_info; - -static u32 bcm2835_pitch; - -struct msg_query { - struct bcm2835_mbox_hdr hdr; - struct bcm2835_mbox_tag_physical_w_h physical_w_h; - u32 end_tag; -}; - -struct msg_setup { - struct bcm2835_mbox_hdr hdr; - struct bcm2835_mbox_tag_physical_w_h physical_w_h; - struct bcm2835_mbox_tag_virtual_w_h virtual_w_h; - struct bcm2835_mbox_tag_depth depth; - struct bcm2835_mbox_tag_pixel_order pixel_order; - struct bcm2835_mbox_tag_alpha_mode alpha_mode; - struct bcm2835_mbox_tag_virtual_offset virtual_offset; - struct bcm2835_mbox_tag_overscan overscan; - struct bcm2835_mbox_tag_allocate_buffer allocate_buffer; - struct bcm2835_mbox_tag_pitch pitch; - u32 end_tag; -}; - -void lcd_ctrl_init(void *lcdbase) +static int bcm2835_video_probe(struct udevice *dev) { - ALLOC_CACHE_ALIGN_BUFFER(struct msg_query, msg_query, 1); - ALLOC_CACHE_ALIGN_BUFFER(struct msg_setup, msg_setup, 1); + struct video_uc_platdata *plat = dev_get_uclass_platdata(dev); + struct video_priv *uc_priv = dev_get_uclass_priv(dev); int ret; - u32 w, h; - u32 fb_start, fb_end; + int w, h, pitch; + ulong fb_base, fb_size, fb_start, fb_end; debug("bcm2835: Query resolution...\n"); - - BCM2835_MBOX_INIT_HDR(msg_query); - BCM2835_MBOX_INIT_TAG_NO_REQ(&msg_query->physical_w_h, - GET_PHYSICAL_W_H); - ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_query->hdr); - if (ret) { - printf("bcm2835: Could not query display resolution\n"); - /* FIXME: How to disable the LCD to prevent errors? hang()? */ - return; - } - - w = msg_query->physical_w_h.body.resp.width; - h = msg_query->physical_w_h.body.resp.height; + ret = bcm2835_get_video_size(&w, &h); + if (ret) + return -EIO; debug("bcm2835: Setting up display for %d x %d\n", w, h); - - BCM2835_MBOX_INIT_HDR(msg_setup); - BCM2835_MBOX_INIT_TAG(&msg_setup->physical_w_h, SET_PHYSICAL_W_H); - msg_setup->physical_w_h.body.req.width = w; - msg_setup->physical_w_h.body.req.height = h; - BCM2835_MBOX_INIT_TAG(&msg_setup->virtual_w_h, SET_VIRTUAL_W_H); - msg_setup->virtual_w_h.body.req.width = w; - msg_setup->virtual_w_h.body.req.height = h; - BCM2835_MBOX_INIT_TAG(&msg_setup->depth, SET_DEPTH); - msg_setup->depth.body.req.bpp = 32; - BCM2835_MBOX_INIT_TAG(&msg_setup->pixel_order, SET_PIXEL_ORDER); - msg_setup->pixel_order.body.req.order = BCM2835_MBOX_PIXEL_ORDER_RGB; - BCM2835_MBOX_INIT_TAG(&msg_setup->alpha_mode, SET_ALPHA_MODE); - msg_setup->alpha_mode.body.req.alpha = BCM2835_MBOX_ALPHA_MODE_IGNORED; - BCM2835_MBOX_INIT_TAG(&msg_setup->virtual_offset, SET_VIRTUAL_OFFSET); - msg_setup->virtual_offset.body.req.x = 0; - msg_setup->virtual_offset.body.req.y = 0; - BCM2835_MBOX_INIT_TAG(&msg_setup->overscan, SET_OVERSCAN); - msg_setup->overscan.body.req.top = 0; - msg_setup->overscan.body.req.bottom = 0; - msg_setup->overscan.body.req.left = 0; - msg_setup->overscan.body.req.right = 0; - BCM2835_MBOX_INIT_TAG(&msg_setup->allocate_buffer, ALLOCATE_BUFFER); - msg_setup->allocate_buffer.body.req.alignment = 0x100; - BCM2835_MBOX_INIT_TAG_NO_REQ(&msg_setup->pitch, GET_PITCH); - - ret = bcm2835_mbox_call_prop(BCM2835_MBOX_PROP_CHAN, &msg_setup->hdr); - if (ret) { - printf("bcm2835: Could not configure display\n"); - /* FIXME: How to disable the LCD to prevent errors? hang()? */ - return; - } - - w = msg_setup->physical_w_h.body.resp.width; - h = msg_setup->physical_w_h.body.resp.height; - bcm2835_pitch = msg_setup->pitch.body.resp.pitch; + ret = bcm2835_set_video_params(&w, &h, 32, BCM2835_MBOX_PIXEL_ORDER_RGB, + BCM2835_MBOX_ALPHA_MODE_IGNORED, + &fb_base, &fb_size, &pitch); debug("bcm2835: Final resolution is %d x %d\n", w, h); - panel_info.vl_col = w; - panel_info.vl_row = h; - panel_info.vl_bpix = LCD_COLOR32; - - gd->fb_base = bus_to_phys( - msg_setup->allocate_buffer.body.resp.fb_address); - /* Enable dcache for the frame buffer */ - fb_start = gd->fb_base & ~(MMU_SECTION_SIZE - 1); - fb_end = gd->fb_base + msg_setup->allocate_buffer.body.resp.fb_size; + fb_start = fb_base & ~(MMU_SECTION_SIZE - 1); + fb_end = fb_base + fb_size; fb_end = ALIGN(fb_end, 1 << MMU_SECTION_SHIFT); mmu_set_region_dcache_behaviour(fb_start, fb_end - fb_start, - DCACHE_WRITEBACK); - lcd_set_flush_dcache(1); -} + DCACHE_WRITEBACK); + video_set_flush_dcache(dev, true); -void lcd_enable(void) -{ -} + uc_priv->xsize = w; + uc_priv->ysize = h; + uc_priv->bpix = VIDEO_BPP32; + plat->base = fb_base; + plat->size = fb_size; -int lcd_get_size(int *line_length) -{ - *line_length = bcm2835_pitch; - return *line_length * panel_info.vl_row; + return 0; } + +static const struct udevice_id bcm2835_video_ids[] = { + { .compatible = "brcm,bcm2835-hdmi" }, + { } +}; + +U_BOOT_DRIVER(bcm2835_video) = { + .name = "bcm2835_video", + .id = UCLASS_VIDEO, + .of_match = bcm2835_video_ids, + .probe = bcm2835_video_probe, +}; diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 2034e3c..bdaf5d4 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -1,5 +1,17 @@ menu "Watchdog Timer Support" +config HW_WATCHDOG + bool + +config BCM2835_WDT + bool "Enable BCM2835/2836 watchdog driver" + select HW_WATCHDOG + help + Say Y here to enable the BCM2835/2836 watchdog + + This provides basic infrastructure to support BCM2835/2836 watchdog + hardware, with a max timeout of ~15secs. + config ULP_WATCHDOG bool "i.MX7ULP watchdog" help diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index dfc7fbd..8378601 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -18,3 +18,4 @@ obj-$(CONFIG_ULP_WATCHDOG) += ulp_wdog.o obj-$(CONFIG_WDT) += wdt-uclass.o obj-$(CONFIG_WDT_SANDBOX) += sandbox_wdt.o obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o +obj-$(CONFIG_BCM2835_WDT) += bcm2835_wdt.o diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c new file mode 100644 index 0000000..6f753ae --- /dev/null +++ b/drivers/watchdog/bcm2835_wdt.c @@ -0,0 +1,35 @@ +/* + * Watchdog driver for Broadcom BCM2835 + * + * Copyright (C) 2017 Paolo Pisati <p.pisati@gmail.com> + * + * SPDX-License-Identifier: GPL-2.0 + */ + +#include <common.h> +#include <efi_loader.h> +#include <asm/io.h> +#include <asm/arch/wdog.h> + +#define SECS_TO_WDOG_TICKS(x) ((x) << 16) +#define MAX_TIMEOUT 0xf /* ~15s */ + +static __efi_runtime_data bool enabled = true; + +extern void reset_cpu(ulong ticks); + +void hw_watchdog_reset(void) +{ + if (enabled) + reset_cpu(SECS_TO_WDOG_TICKS(MAX_TIMEOUT)); +} + +void hw_watchdog_init(void) +{ + hw_watchdog_reset(); +} + +void __efi_runtime hw_watchdog_disable(void) +{ + enabled = false; +} |