diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/clk/clk_stm32mp1.c | 120 | ||||
-rw-r--r-- | drivers/core/uclass.c | 2 | ||||
-rw-r--r-- | drivers/misc/misc-uclass.c | 3 | ||||
-rw-r--r-- | drivers/mmc/mmc.c | 28 | ||||
-rw-r--r-- | drivers/mmc/omap_hsmmc.c | 108 | ||||
-rw-r--r-- | drivers/mmc/renesas-sdhi.c | 10 | ||||
-rw-r--r-- | drivers/mmc/s5p_sdhci.c | 50 | ||||
-rw-r--r-- | drivers/mmc/tmio-common.c | 11 | ||||
-rw-r--r-- | drivers/mmc/tmio-common.h | 1 | ||||
-rw-r--r-- | drivers/mmc/uniphier-sd.c | 1 | ||||
-rw-r--r-- | drivers/pci/pcie_dw_mvebu.c | 4 | ||||
-rw-r--r-- | drivers/power/regulator/regulator-uclass.c | 13 | ||||
-rw-r--r-- | drivers/serial/serial_pl01x.c | 2 | ||||
-rw-r--r-- | drivers/sound/Kconfig | 14 | ||||
-rw-r--r-- | drivers/sound/Makefile | 1 | ||||
-rw-r--r-- | drivers/sound/max98088.c | 424 | ||||
-rw-r--r-- | drivers/sound/max98088.h | 192 | ||||
-rw-r--r-- | drivers/sound/max98090.c | 7 | ||||
-rw-r--r-- | drivers/sound/max98095.c | 7 | ||||
-rw-r--r-- | drivers/sound/maxim_codec.c | 3 | ||||
-rw-r--r-- | drivers/sound/samsung-i2s.c | 16 | ||||
-rw-r--r-- | drivers/sound/samsung_sound.c | 6 | ||||
-rw-r--r-- | drivers/watchdog/Kconfig | 2 | ||||
-rw-r--r-- | drivers/watchdog/bcm6345_wdt.c | 10 |
24 files changed, 905 insertions, 130 deletions
diff --git a/drivers/clk/clk_stm32mp1.c b/drivers/clk/clk_stm32mp1.c index b7c5d34fe0..aebc6f0a34 100644 --- a/drivers/clk/clk_stm32mp1.c +++ b/drivers/clk/clk_stm32mp1.c @@ -165,6 +165,7 @@ /* used for ALL PLLNCR registers */ #define RCC_PLLNCR_PLLON BIT(0) #define RCC_PLLNCR_PLLRDY BIT(1) +#define RCC_PLLNCR_SSCG_CTRL BIT(2) #define RCC_PLLNCR_DIVPEN BIT(4) #define RCC_PLLNCR_DIVQEN BIT(5) #define RCC_PLLNCR_DIVREN BIT(6) @@ -241,7 +242,6 @@ enum stm32mp1_parent_id { _LSI, _LSE, _I2S_CKIN, - _USB_PHY_48, NB_OSC, /* other parent source */ @@ -273,6 +273,7 @@ enum stm32mp1_parent_id { _CK_MPU, _CK_MCU, _DSI_PHY, + _USB_PHY_48, _PARENT_NB, _UNKNOWN_ID = 0xff, }; @@ -536,6 +537,7 @@ static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { STM32MP1_CLK_SET_CLR(RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL), STM32MP1_CLK_SET_CLR(RCC_MP_AHB3ENSETR, 11, HSEM, _UNKNOWN_SEL), + STM32MP1_CLK_SET_CLR(RCC_MP_AHB3ENSETR, 12, IPCC, _UNKNOWN_SEL), STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL), STM32MP1_CLK_SET_CLR(RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL), @@ -665,8 +667,8 @@ static const u8 stm32mp1_axi_div[8] = { 1, 2, 3, 4, 4, 4, 4, 4 }; -#ifdef DEBUG -static const char * const stm32mp1_clk_parent_name[_PARENT_NB] = { +static const __maybe_unused +char * const stm32mp1_clk_parent_name[_PARENT_NB] = { [_HSI] = "HSI", [_HSE] = "HSE", [_CSI] = "CSI", @@ -704,7 +706,8 @@ static const char * const stm32mp1_clk_parent_name[_PARENT_NB] = { [_DSI_PHY] = "DSI_PHY_PLL", }; -static const char * const stm32mp1_clk_parent_sel_name[_PARENT_SEL_NB] = { +static const __maybe_unused +char * const stm32mp1_clk_parent_sel_name[_PARENT_SEL_NB] = { [_I2C12_SEL] = "I2C12", [_I2C35_SEL] = "I2C35", [_I2C46_SEL] = "I2C46", @@ -723,7 +726,6 @@ static const char * const stm32mp1_clk_parent_sel_name[_PARENT_SEL_NB] = { [_DSI_SEL] = "DSI", [_ADC12_SEL] = "ADC12", }; -#endif static const struct stm32mp1_clk_data stm32mp1_data = { .gate = stm32mp1_clk_gate, @@ -1079,7 +1081,7 @@ static ulong stm32mp1_clk_get(struct stm32mp1_clk_priv *priv, int p) break; /* other */ case _USB_PHY_48: - clock = stm32mp1_clk_get_fixed(priv, _USB_PHY_48); + clock = 48000000; break; case _DSI_PHY: { @@ -1179,10 +1181,7 @@ static void stm32mp1_ls_osc_set(int enable, fdt_addr_t rcc, u32 offset, static void stm32mp1_hs_ocs_set(int enable, fdt_addr_t rcc, u32 mask_on) { - if (enable) - setbits_le32(rcc + RCC_OCENSETR, mask_on); - else - setbits_le32(rcc + RCC_OCENCLRR, mask_on); + writel(mask_on, rcc + (enable ? RCC_OCENSETR : RCC_OCENCLRR)); } static int stm32mp1_osc_wait(int enable, fdt_addr_t rcc, u32 offset, @@ -1253,20 +1252,20 @@ static void stm32mp1_lsi_set(fdt_addr_t rcc, int enable) static void stm32mp1_hse_enable(fdt_addr_t rcc, int bypass, int digbyp, int css) { if (digbyp) - setbits_le32(rcc + RCC_OCENSETR, RCC_OCENR_DIGBYP); + writel(RCC_OCENR_DIGBYP, rcc + RCC_OCENSETR); if (bypass || digbyp) - setbits_le32(rcc + RCC_OCENSETR, RCC_OCENR_HSEBYP); + writel(RCC_OCENR_HSEBYP, rcc + RCC_OCENSETR); stm32mp1_hs_ocs_set(1, rcc, RCC_OCENR_HSEON); stm32mp1_osc_wait(1, rcc, RCC_OCRDYR, RCC_OCRDYR_HSERDY); if (css) - setbits_le32(rcc + RCC_OCENSETR, RCC_OCENR_HSECSSON); + writel(RCC_OCENR_HSECSSON, rcc + RCC_OCENSETR); } static void stm32mp1_csi_set(fdt_addr_t rcc, int enable) { - stm32mp1_ls_osc_set(enable, rcc, RCC_OCENSETR, RCC_OCENR_CSION); + stm32mp1_hs_ocs_set(enable, rcc, RCC_OCENR_CSION); stm32mp1_osc_wait(enable, rcc, RCC_OCRDYR, RCC_OCRDYR_CSIRDY); } @@ -1321,7 +1320,10 @@ static void pll_start(struct stm32mp1_clk_priv *priv, int pll_id) { const struct stm32mp1_clk_pll *pll = priv->data->pll; - writel(RCC_PLLNCR_PLLON, priv->base + pll[pll_id].pllxcr); + clrsetbits_le32(priv->base + pll[pll_id].pllxcr, + RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | + RCC_PLLNCR_DIVREN, + RCC_PLLNCR_PLLON); } static int pll_output(struct stm32mp1_clk_priv *priv, int pll_id, int output) @@ -1440,6 +1442,8 @@ static void pll_csg(struct stm32mp1_clk_priv *priv, int pll_id, u32 *csg) RCC_PLLNCSGR_SSCG_MODE_MASK); writel(pllxcsg, priv->base + pll[pll_id].pllxcsgr); + + setbits_le32(priv->base + pll[pll_id].pllxcr, RCC_PLLNCR_SSCG_CTRL); } static int set_clksrc(struct stm32mp1_clk_priv *priv, unsigned int clksrc) @@ -1471,10 +1475,15 @@ static void stgen_config(struct stm32mp1_clk_priv *priv) rate = stm32mp1_clk_get(priv, p); if (cntfid0 != rate) { + u64 counter; + pr_debug("System Generic Counter (STGEN) update\n"); clrbits_le32(stgenc + STGENC_CNTCR, STGENC_CNTCR_EN); - writel(0x0, stgenc + STGENC_CNTCVL); - writel(0x0, stgenc + STGENC_CNTCVU); + counter = (u64)readl(stgenc + STGENC_CNTCVL); + counter |= ((u64)(readl(stgenc + STGENC_CNTCVU))) << 32; + counter = lldiv(counter * (u64)rate, cntfid0); + writel((u32)counter, stgenc + STGENC_CNTCVL); + writel((u32)(counter >> 32), stgenc + STGENC_CNTCVU); writel(rate, stgenc + STGENC_CNTFID0); setbits_le32(stgenc + STGENC_CNTCR, STGENC_CNTCR_EN); @@ -1859,7 +1868,7 @@ static void stm32mp1_osc_init(struct udevice *dev) [_HSE] = "clk-hse", [_CSI] = "clk-csi", [_I2S_CKIN] = "i2s_ckin", - [_USB_PHY_48] = "ck_usbo_48m"}; + }; for (i = 0; i < NB_OSC; i++) { stm32mp1_osc_clk_init(name[i], priv, i); @@ -1867,6 +1876,54 @@ static void stm32mp1_osc_init(struct udevice *dev) } } +static void __maybe_unused stm32mp1_clk_dump(struct stm32mp1_clk_priv *priv) +{ + char buf[32]; + int i, s, p; + + printf("Clocks:\n"); + for (i = 0; i < _PARENT_NB; i++) { + printf("- %s : %s MHz\n", + stm32mp1_clk_parent_name[i], + strmhz(buf, stm32mp1_clk_get(priv, i))); + } + printf("Source Clocks:\n"); + for (i = 0; i < _PARENT_SEL_NB; i++) { + p = (readl(priv->base + priv->data->sel[i].offset) >> + priv->data->sel[i].src) & priv->data->sel[i].msk; + if (p < priv->data->sel[i].nb_parent) { + s = priv->data->sel[i].parent[p]; + printf("- %s(%d) => parent %s(%d)\n", + stm32mp1_clk_parent_sel_name[i], i, + stm32mp1_clk_parent_name[s], s); + } else { + printf("- %s(%d) => parent index %d is invalid\n", + stm32mp1_clk_parent_sel_name[i], i, p); + } + } +} + +#ifdef CONFIG_CMD_CLK +int soc_clk_dump(void) +{ + struct udevice *dev; + struct stm32mp1_clk_priv *priv; + int ret; + + ret = uclass_get_device_by_driver(UCLASS_CLK, + DM_GET_DRIVER(stm32mp1_clock), + &dev); + if (ret) + return ret; + + priv = dev_get_priv(dev); + + stm32mp1_clk_dump(priv); + + return 0; +} +#endif + static int stm32mp1_clk_probe(struct udevice *dev) { int result = 0; @@ -1890,6 +1947,33 @@ static int stm32mp1_clk_probe(struct udevice *dev) result = stm32mp1_clktree(dev); #endif +#ifndef CONFIG_SPL_BUILD +#if defined(DEBUG) + /* display debug information for probe after relocation */ + if (gd->flags & GD_FLG_RELOC) + stm32mp1_clk_dump(priv); +#endif + +#if defined(CONFIG_DISPLAY_CPUINFO) + if (gd->flags & GD_FLG_RELOC) { + char buf[32]; + + printf("Clocks:\n"); + printf("- MPU : %s MHz\n", + strmhz(buf, stm32mp1_clk_get(priv, _CK_MPU))); + printf("- MCU : %s MHz\n", + strmhz(buf, stm32mp1_clk_get(priv, _CK_MCU))); + printf("- AXI : %s MHz\n", + strmhz(buf, stm32mp1_clk_get(priv, _ACLK))); + printf("- PER : %s MHz\n", + strmhz(buf, stm32mp1_clk_get(priv, _CK_PER))); + /* DDRPHYC father */ + printf("- DDR : %s MHz\n", + strmhz(buf, stm32mp1_clk_get(priv, _PLL2_R))); + } +#endif /* CONFIG_DISPLAY_CPUINFO */ +#endif + return result; } diff --git a/drivers/core/uclass.c b/drivers/core/uclass.c index a622f07941..fc3157de39 100644 --- a/drivers/core/uclass.c +++ b/drivers/core/uclass.c @@ -225,7 +225,7 @@ int uclass_find_first_device(enum uclass_id id, struct udevice **devp) if (ret) return ret; if (list_empty(&uc->dev_head)) - return 0; + return -ENODEV; *devp = list_first_entry(&uc->dev_head, struct udevice, uclass_node); diff --git a/drivers/misc/misc-uclass.c b/drivers/misc/misc-uclass.c index f240cda5c0..55381edc98 100644 --- a/drivers/misc/misc-uclass.c +++ b/drivers/misc/misc-uclass.c @@ -68,4 +68,7 @@ int misc_set_enabled(struct udevice *dev, bool val) UCLASS_DRIVER(misc) = { .id = UCLASS_MISC, .name = "misc", +#if CONFIG_IS_ENABLED(OF_CONTROL) && !CONFIG_IS_ENABLED(OF_PLATDATA) + .post_bind = dm_scan_fdt_dev, +#endif }; diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 84d157ff40..b04345a1e1 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -724,7 +724,8 @@ static int mmc_send_ext_csd(struct mmc *mmc, u8 *ext_csd) return err; } -int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value) +static int __mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value, + bool send_status) { struct mmc_cmd cmd; int timeout = 1000; @@ -740,19 +741,29 @@ int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value) while (retries > 0) { ret = mmc_send_cmd(mmc, &cmd, NULL); - /* Waiting for the ready status */ - if (!ret) { - ret = mmc_send_status(mmc, timeout); - return ret; + if (ret) { + retries--; + continue; + } + + if (!send_status) { + mdelay(50); + return 0; } - retries--; + /* Waiting for the ready status */ + return mmc_send_status(mmc, timeout); } return ret; } +int mmc_switch(struct mmc *mmc, u8 set, u8 index, u8 value) +{ + return __mmc_switch(mmc, set, index, value, true); +} + #if !CONFIG_IS_ENABLED(MMC_TINY) static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode, bool hsdowngrade) @@ -784,8 +795,9 @@ static int mmc_set_card_speed(struct mmc *mmc, enum bus_mode mode, default: return -EINVAL; } - err = mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, - speed_bits); + + err = __mmc_switch(mmc, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, + speed_bits, !hsdowngrade); if (err) return err; diff --git a/drivers/mmc/omap_hsmmc.c b/drivers/mmc/omap_hsmmc.c index 5cb97eb02a..826a39fad7 100644 --- a/drivers/mmc/omap_hsmmc.c +++ b/drivers/mmc/omap_hsmmc.c @@ -47,6 +47,7 @@ #endif #include <dm.h> #include <power/regulator.h> +#include <thermal.h> DECLARE_GLOBAL_DATA_PTR; @@ -470,21 +471,21 @@ static int omap_hsmmc_set_io_regulator(struct mmc *mmc, int mV) return 0; /* Disable PBIAS */ - ret = regulator_set_enable(priv->pbias_supply, false); - if (ret && ret != -ENOSYS) + ret = regulator_set_enable_if_allowed(priv->pbias_supply, false); + if (ret) return ret; /* Turn off IO voltage */ - ret = regulator_set_enable(mmc->vqmmc_supply, false); - if (ret && ret != -ENOSYS) + ret = regulator_set_enable_if_allowed(mmc->vqmmc_supply, false); + if (ret) return ret; /* Program a new IO voltage value */ ret = regulator_set_value(mmc->vqmmc_supply, uV); if (ret) return ret; /* Turn on IO voltage */ - ret = regulator_set_enable(mmc->vqmmc_supply, true); - if (ret && ret != -ENOSYS) + ret = regulator_set_enable_if_allowed(mmc->vqmmc_supply, true); + if (ret) return ret; /* Program PBIAS voltage*/ @@ -492,8 +493,8 @@ static int omap_hsmmc_set_io_regulator(struct mmc *mmc, int mV) if (ret && ret != -ENOSYS) return ret; /* Enable PBIAS */ - ret = regulator_set_enable(priv->pbias_supply, true); - if (ret && ret != -ENOSYS) + ret = regulator_set_enable_if_allowed(priv->pbias_supply, true); + if (ret) return ret; return 0; @@ -622,6 +623,10 @@ static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode) u32 phase_delay = 0; u32 start_window = 0, max_window = 0; u32 length = 0, max_len = 0; + bool single_point_failure = false; + struct udevice *thermal_dev; + int temperature; + int i; mmc_base = priv->base_addr; val = readl(&mmc_base->capa2); @@ -632,9 +637,25 @@ static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode) ((mmc->selected_mode == UHS_SDR50) && (val & CAPA2_TSDR50)))) return 0; + ret = uclass_first_device(UCLASS_THERMAL, &thermal_dev); + if (ret) { + printf("Couldn't get thermal device for tuning\n"); + return ret; + } + ret = thermal_get_temp(thermal_dev, &temperature); + if (ret) { + printf("Couldn't get temperature for tuning\n"); + return ret; + } val = readl(&mmc_base->dll); val |= DLL_SWT; writel(val, &mmc_base->dll); + + /* + * Stage 1: Search for a maximum pass window ignoring any + * any single point failures. If the tuning value ends up + * near it, move away from it in stage 2 below + */ while (phase_delay <= MAX_PHASE_DELAY) { omap_hsmmc_set_dll(mmc, phase_delay); @@ -643,10 +664,16 @@ static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode) if (cur_match) { if (prev_match) { length++; + } else if (single_point_failure) { + /* ignore single point failure */ + length++; + single_point_failure = false; } else { start_window = phase_delay; length = 1; } + } else { + single_point_failure = prev_match; } if (length > max_len) { @@ -668,8 +695,71 @@ static int omap_hsmmc_execute_tuning(struct udevice *dev, uint opcode) ret = -EIO; goto tuning_error; } + /* + * Assign tuning value as a ratio of maximum pass window based + * on temperature + */ + if (temperature < -20000) + phase_delay = min(max_window + 4 * max_len - 24, + max_window + + DIV_ROUND_UP(13 * max_len, 16) * 4); + else if (temperature < 20000) + phase_delay = max_window + DIV_ROUND_UP(9 * max_len, 16) * 4; + else if (temperature < 40000) + phase_delay = max_window + DIV_ROUND_UP(8 * max_len, 16) * 4; + else if (temperature < 70000) + phase_delay = max_window + DIV_ROUND_UP(7 * max_len, 16) * 4; + else if (temperature < 90000) + phase_delay = max_window + DIV_ROUND_UP(5 * max_len, 16) * 4; + else if (temperature < 120000) + phase_delay = max_window + DIV_ROUND_UP(4 * max_len, 16) * 4; + else + phase_delay = max_window + DIV_ROUND_UP(3 * max_len, 16) * 4; + + /* + * Stage 2: Search for a single point failure near the chosen tuning + * value in two steps. First in the +3 to +10 range and then in the + * +2 to -10 range. If found, move away from it in the appropriate + * direction by the appropriate amount depending on the temperature. + */ + for (i = 3; i <= 10; i++) { + omap_hsmmc_set_dll(mmc, phase_delay + i); + if (mmc_send_tuning(mmc, opcode, NULL)) { + if (temperature < 10000) + phase_delay += i + 6; + else if (temperature < 20000) + phase_delay += i - 12; + else if (temperature < 70000) + phase_delay += i - 8; + else if (temperature < 90000) + phase_delay += i - 6; + else + phase_delay += i - 6; + + goto single_failure_found; + } + } + + for (i = 2; i >= -10; i--) { + omap_hsmmc_set_dll(mmc, phase_delay + i); + if (mmc_send_tuning(mmc, opcode, NULL)) { + if (temperature < 10000) + phase_delay += i + 12; + else if (temperature < 20000) + phase_delay += i + 8; + else if (temperature < 70000) + phase_delay += i + 8; + else if (temperature < 90000) + phase_delay += i + 10; + else + phase_delay += i + 12; + + goto single_failure_found; + } + } + +single_failure_found: - phase_delay = max_window + 4 * ((3 * max_len) >> 2); omap_hsmmc_set_dll(mmc, phase_delay); mmc_reset_controller_fsm(mmc_base, SYSCTL_SRD); diff --git a/drivers/mmc/renesas-sdhi.c b/drivers/mmc/renesas-sdhi.c index 733b6d62f5..a556acd5cb 100644 --- a/drivers/mmc/renesas-sdhi.c +++ b/drivers/mmc/renesas-sdhi.c @@ -462,6 +462,16 @@ static void renesas_sdhi_filter_caps(struct udevice *dev) priv->nrtaps = 4; else priv->nrtaps = 8; + + /* H3 ES1.x and M3W ES1.0 uses bit 17 for DTRAEND */ + if (((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7795) && + (rmobile_get_cpu_rev_integer() <= 1)) || + ((rmobile_get_cpu_type() == RMOBILE_CPU_TYPE_R8A7796) && + (rmobile_get_cpu_rev_integer() == 1) && + (rmobile_get_cpu_rev_fraction() == 0))) + priv->read_poll_flag = TMIO_SD_DMA_INFO1_END_RD; + else + priv->read_poll_flag = TMIO_SD_DMA_INFO1_END_RD2; } static int renesas_sdhi_probe(struct udevice *dev) diff --git a/drivers/mmc/s5p_sdhci.c b/drivers/mmc/s5p_sdhci.c index 591a3bce08..9dd0b865eb 100644 --- a/drivers/mmc/s5p_sdhci.c +++ b/drivers/mmc/s5p_sdhci.c @@ -118,9 +118,6 @@ int s5p_sdhci_init(u32 regbase, int index, int bus_width) return s5p_sdhci_core_init(host); } -#if CONFIG_IS_ENABLED(OF_CONTROL) -struct sdhci_host sdhci_host[SDHCI_MAX_HOSTS]; - static int do_sdhci_init(struct sdhci_host *host) { int dev_id, flag, ret; @@ -191,53 +188,6 @@ static int sdhci_get_config(const void *blob, int node, struct sdhci_host *host) return 0; } -static int process_nodes(const void *blob, int node_list[], int count) -{ - struct sdhci_host *host; - int i, node, ret; - int failed = 0; - - debug("%s: count = %d\n", __func__, count); - - /* build sdhci_host[] for each controller */ - for (i = 0; i < count; i++) { - node = node_list[i]; - if (node <= 0) - continue; - - host = &sdhci_host[i]; - - ret = sdhci_get_config(blob, node, host); - if (ret) { - printf("%s: failed to decode dev %d (%d)\n", __func__, i, ret); - failed++; - continue; - } - - ret = do_sdhci_init(host); - if (ret && ret != -ENODEV) { - printf("%s: failed to initialize dev %d (%d)\n", __func__, i, ret); - failed++; - } - } - - /* we only consider it an error when all nodes fail */ - return (failed == count ? -1 : 0); -} - -int exynos_mmc_init(const void *blob) -{ - int count; - int node_list[SDHCI_MAX_HOSTS]; - - count = fdtdec_find_aliases_for_id(blob, "mmc", - COMPAT_SAMSUNG_EXYNOS_MMC, node_list, - SDHCI_MAX_HOSTS); - - return process_nodes(blob, node_list, count); -} -#endif - #ifdef CONFIG_DM_MMC static int s5p_sdhci_probe(struct udevice *dev) { diff --git a/drivers/mmc/tmio-common.c b/drivers/mmc/tmio-common.c index 201492001f..2421915a07 100644 --- a/drivers/mmc/tmio-common.c +++ b/drivers/mmc/tmio-common.c @@ -347,12 +347,10 @@ static int tmio_sd_dma_xfer(struct udevice *dev, struct mmc_data *data) /* * The DMA READ completion flag position differs on Socionext * and Renesas SoCs. It is bit 20 on Socionext SoCs and using - * bit 17 is a hardware bug and forbidden. It is bit 17 on - * Renesas SoCs and bit 20 does not work on them. + * bit 17 is a hardware bug and forbidden. It is either bit 17 + * or bit 20 on Renesas SoCs, depending on SoC. */ - poll_flag = (priv->caps & TMIO_SD_CAP_RCAR) ? - TMIO_SD_DMA_INFO1_END_RD : - TMIO_SD_DMA_INFO1_END_RD2; + poll_flag = priv->read_poll_flag; tmp |= TMIO_SD_DMA_MODE_DIR_RD; } else { buf = (void *)data->src; @@ -369,6 +367,9 @@ static int tmio_sd_dma_xfer(struct udevice *dev, struct mmc_data *data) ret = tmio_sd_dma_wait_for_irq(dev, poll_flag, data->blocks); + if (poll_flag == TMIO_SD_DMA_INFO1_END_RD) + udelay(1); + __dma_unmap_single(dma_addr, len, dir); return ret; diff --git a/drivers/mmc/tmio-common.h b/drivers/mmc/tmio-common.h index 192026ce3e..58ce3d65b0 100644 --- a/drivers/mmc/tmio-common.h +++ b/drivers/mmc/tmio-common.h @@ -119,6 +119,7 @@ struct tmio_sd_priv { void __iomem *regbase; unsigned int version; u32 caps; + u32 read_poll_flag; #define TMIO_SD_CAP_NONREMOVABLE BIT(0) /* Nonremovable e.g. eMMC */ #define TMIO_SD_CAP_DMA_INTERNAL BIT(1) /* have internal DMA engine */ #define TMIO_SD_CAP_DIV1024 BIT(2) /* divisor 1024 is available */ diff --git a/drivers/mmc/uniphier-sd.c b/drivers/mmc/uniphier-sd.c index 6539880ab5..8f89bda233 100644 --- a/drivers/mmc/uniphier-sd.c +++ b/drivers/mmc/uniphier-sd.c @@ -47,6 +47,7 @@ static int uniphier_sd_probe(struct udevice *dev) struct tmio_sd_priv *priv = dev_get_priv(dev); priv->clk_get_rate = uniphier_sd_clk_get_rate; + priv->read_poll_flag = TMIO_SD_DMA_INFO1_END_RD2; #ifndef CONFIG_SPL_BUILD int ret; diff --git a/drivers/pci/pcie_dw_mvebu.c b/drivers/pci/pcie_dw_mvebu.c index 8081005c27..95fb41966f 100644 --- a/drivers/pci/pcie_dw_mvebu.c +++ b/drivers/pci/pcie_dw_mvebu.c @@ -489,7 +489,9 @@ static int pcie_dw_mvebu_probe(struct udevice *dev) * using this GPIO. */ if (dm_gpio_is_valid(&reset_gpio)) { - dm_gpio_set_value(&reset_gpio, 1); + dm_gpio_set_value(&reset_gpio, 1); /* assert */ + mdelay(200); + dm_gpio_set_value(&reset_gpio, 0); /* de-assert */ mdelay(200); } #else diff --git a/drivers/power/regulator/regulator-uclass.c b/drivers/power/regulator/regulator-uclass.c index 39e46279d5..6f355b969a 100644 --- a/drivers/power/regulator/regulator-uclass.c +++ b/drivers/power/regulator/regulator-uclass.c @@ -113,11 +113,22 @@ int regulator_set_enable(struct udevice *dev, bool enable) uc_pdata = dev_get_uclass_platdata(dev); if (!enable && uc_pdata->always_on) - return 0; + return -EACCES; return ops->set_enable(dev, enable); } +int regulator_set_enable_if_allowed(struct udevice *dev, bool enable) +{ + int ret; + + ret = regulator_set_enable(dev, enable); + if (ret == -ENOSYS || ret == -EACCES) + return 0; + + return ret; +} + int regulator_get_mode(struct udevice *dev) { const struct dm_regulator_ops *ops = dev_get_driver_ops(dev); diff --git a/drivers/serial/serial_pl01x.c b/drivers/serial/serial_pl01x.c index 12512f6578..2a5f256184 100644 --- a/drivers/serial/serial_pl01x.c +++ b/drivers/serial/serial_pl01x.c @@ -363,9 +363,7 @@ U_BOOT_DRIVER(serial_pl01x) = { .platdata_auto_alloc_size = sizeof(struct pl01x_serial_platdata), .probe = pl01x_serial_probe, .ops = &pl01x_serial_ops, -#if !CONFIG_IS_ENABLED(OF_CONTROL) .flags = DM_FLAG_PRE_RELOC, -#endif .priv_auto_alloc_size = sizeof(struct pl01x_priv), }; diff --git a/drivers/sound/Kconfig b/drivers/sound/Kconfig index 22e379681d..40f4f7598a 100644 --- a/drivers/sound/Kconfig +++ b/drivers/sound/Kconfig @@ -32,7 +32,7 @@ config I2S_ROCKCHIP config I2S_SAMSUNG bool "Enable I2C support for Samsung SoCs" - depends on SOUND + depends on I2S help Samsung Exynos SoCs support an I2S interface for sending audio data to an audio codec. This option enables support for this, @@ -40,9 +40,17 @@ config I2S_SAMSUNG option provides an implementation for sound_init() and sound_play(). +config SOUND_MAX98088 + bool "Support Maxim max98088 audio codec" + depends on I2S + help + Enable the max98088 audio codec. This is connected via I2S for + audio data and I2C for codec control. At present it only works + with the Samsung I2S driver. + config SOUND_MAX98090 bool "Support Maxim max98090 audio codec" - depends on I2S_SAMSUNG + depends on I2S help Enable the max98090 audio codec. This is connected via I2S for audio data and I2C for codec control. At present it only works @@ -50,7 +58,7 @@ config SOUND_MAX98090 config SOUND_MAX98095 bool "Support Maxim max98095 audio codec" - depends on I2S_SAMSUNG + depends on I2S help Enable the max98095 audio codec. This is connected via I2S for audio data and I2C for codec control. At present it only works diff --git a/drivers/sound/Makefile b/drivers/sound/Makefile index d0bf51bab6..170e06ad53 100644 --- a/drivers/sound/Makefile +++ b/drivers/sound/Makefile @@ -12,5 +12,6 @@ obj-$(CONFIG_SOUND_SANDBOX) += sandbox.o obj-$(CONFIG_I2S_ROCKCHIP) += rockchip_i2s.o rockchip_sound.o obj-$(CONFIG_I2S_SAMSUNG) += samsung_sound.o obj-$(CONFIG_SOUND_WM8994) += wm8994.o +obj-$(CONFIG_SOUND_MAX98088) += max98088.o maxim_codec.o obj-$(CONFIG_SOUND_MAX98090) += max98090.o maxim_codec.o obj-$(CONFIG_SOUND_MAX98095) += max98095.o maxim_codec.o diff --git a/drivers/sound/max98088.c b/drivers/sound/max98088.c new file mode 100644 index 0000000000..332254d5aa --- /dev/null +++ b/drivers/sound/max98088.c @@ -0,0 +1,424 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * max98088.c -- MAX98088 ALSA SoC Audio driver + * + * Copyright 2010 Maxim Integrated Products + * + * Modified for U-Boot by Chih-Chung Chang (chihchung@chromium.org), + * following the changes made in max98095.c + */ + +#include <common.h> +#include <audio_codec.h> +#include <div64.h> +#include <dm.h> +#include <i2c.h> +#include <i2s.h> +#include <sound.h> +#include <asm/gpio.h> +#include "maxim_codec.h" +#include "max98088.h" + +/* codec mclk clock divider coefficients. Index 0 is reserved. */ +static const int rate_table[] = {0, 8000, 11025, 16000, 22050, 24000, 32000, + 44100, 48000, 88200, 96000}; + +/* + * codec mclk clock divider coefficients based on sampling rate + * + * @param rate sampling rate + * @param value address of indexvalue to be stored + * + * @return 0 for success or negative error code. + */ +static int rate_value(int rate, u8 *value) +{ + int i; + + for (i = 1; i < ARRAY_SIZE(rate_table); i++) { + if (rate_table[i] >= rate) { + *value = i; + return 0; + } + } + *value = 1; + + return -EINVAL; +} + +/* + * Sets hw params for max98088 + * + * @priv: max98088 information pointer + * @rate: Sampling rate + * @bits_per_sample: Bits per sample + * + * @return -EIO for error, 0 for success. + */ +int max98088_hw_params(struct maxim_priv *priv, unsigned int rate, + unsigned int bits_per_sample) +{ + int error; + u8 regval; + + switch (bits_per_sample) { + case 16: + error = maxim_bic_or(priv, M98088_REG_DAI1_FORMAT, + M98088_DAI_WS, 0); + break; + case 24: + error = maxim_bic_or(priv, M98088_REG_DAI1_FORMAT, + M98088_DAI_WS, M98088_DAI_WS); + break; + default: + debug("%s: Illegal bits per sample %d.\n", + __func__, bits_per_sample); + return -EINVAL; + } + + error |= maxim_bic_or(priv, M98088_REG_PWR_SYS, M98088_SHDNRUN, 0); + + if (rate_value(rate, ®val)) { + debug("%s: Failed to set sample rate to %d.\n", + __func__, rate); + return -EIO; + } + + error |= maxim_bic_or(priv, M98088_REG_DAI1_CLKMODE, + M98088_CLKMODE_MASK, regval << 4); + priv->rate = rate; + + /* Update sample rate mode */ + if (rate < 50000) + error |= maxim_bic_or(priv, M98088_REG_DAI1_FILTERS, + M98088_DAI_DHF, 0); + else + error |= maxim_bic_or(priv, M98088_REG_DAI1_FILTERS, + M98088_DAI_DHF, M98088_DAI_DHF); + + error |= maxim_bic_or(priv, M98088_REG_PWR_SYS, M98088_SHDNRUN, + M98088_SHDNRUN); + + if (error < 0) { + debug("%s: Error setting hardware params.\n", __func__); + return -EIO; + } + priv->rate = rate; + + return 0; +} + +/* + * Configures Audio interface system clock for the given frequency + * + * @priv: max98088 information + * @freq: Sampling frequency in Hz + * + * @return -EIO for error, 0 for success. + */ +int max98088_set_sysclk(struct maxim_priv *priv, unsigned int freq) +{ + int error = 0; + u8 pwr; + + /* Requested clock frequency is already setup */ + if (freq == priv->sysclk) + return 0; + + /* + * Setup clocks for slave mode, and using the PLL + * PSCLK = 0x01 (when master clk is 10MHz to 20MHz) + * 0x02 (when master clk is 20MHz to 30MHz).. + */ + if (freq >= 10000000 && freq < 20000000) { + error = maxim_i2c_write(priv, M98088_REG_SYS_CLK, 0x10); + } else if ((freq >= 20000000) && (freq < 30000000)) { + error = maxim_i2c_write(priv, M98088_REG_SYS_CLK, 0x20); + } else { + debug("%s: Invalid master clock frequency\n", __func__); + return -EIO; + } + + error |= maxim_i2c_read(priv, M98088_REG_PWR_SYS, &pwr); + if (pwr & M98088_SHDNRUN) { + error |= maxim_bic_or(priv, M98088_REG_PWR_SYS, + M98088_SHDNRUN, 0); + error |= maxim_bic_or(priv, M98088_REG_PWR_SYS, + M98088_SHDNRUN, M98088_SHDNRUN); + } + + debug("%s: Clock at %uHz\n", __func__, freq); + if (error < 0) + return -EIO; + + priv->sysclk = freq; + + return 0; +} + +/* + * Sets Max98090 I2S format + * + * @priv: max98088 information + * @fmt: i2S format - supports a subset of the options defined in i2s.h. + * + * @return -EIO for error, 0 for success. + */ +int max98088_set_fmt(struct maxim_priv *priv, int fmt) +{ + u8 reg15val; + u8 reg14val = 0; + int error = 0; + + if (fmt == priv->fmt) + return 0; + + priv->fmt = fmt; + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + /* Slave mode PLL */ + error |= maxim_i2c_write(priv, M98088_REG_DAI1_CLKCFG_HI, + 0x80); + error |= maxim_i2c_write(priv, M98088_REG_DAI1_CLKCFG_LO, + 0x00); + break; + case SND_SOC_DAIFMT_CBM_CFM: + /* Set to master mode */ + reg14val |= M98088_DAI_MAS; + break; + case SND_SOC_DAIFMT_CBS_CFM: + case SND_SOC_DAIFMT_CBM_CFS: + default: + debug("%s: Clock mode unsupported\n", __func__); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + reg14val |= M98088_DAI_DLY; + break; + case SND_SOC_DAIFMT_LEFT_J: + break; + default: + debug("%s: Unrecognized format.\n", __func__); + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_NB_IF: + reg14val |= M98088_DAI_WCI; + break; + case SND_SOC_DAIFMT_IB_NF: + reg14val |= M98088_DAI_BCI; + break; + case SND_SOC_DAIFMT_IB_IF: + reg14val |= M98088_DAI_BCI | M98088_DAI_WCI; + break; + default: + debug("%s: Unrecognized inversion settings.\n", __func__); + return -EINVAL; + } + + error |= maxim_bic_or(priv, M98088_REG_DAI1_FORMAT, + M98088_DAI_MAS | M98088_DAI_DLY | M98088_DAI_BCI | + M98088_DAI_WCI, reg14val); + reg15val = M98088_DAI_BSEL64; + error |= maxim_i2c_write(priv, M98088_REG_DAI1_CLOCK, reg15val); + + if (error < 0) { + debug("%s: Error setting i2s format.\n", __func__); + return -EIO; + } + + return 0; +} + +/* + * max98088_reset() - reset the audio codec + * + * @priv: max98088 information + * @return -EIO for error, 0 for success. + */ +static int max98088_reset(struct maxim_priv *priv) +{ + int ret, i; + u8 val; + + /* + * Reset to hardware default for registers, as there is not a soft + * reset hardware control register. + */ + for (i = M98088_REG_IRQ_ENABLE; i <= M98088_REG_PWR_SYS; i++) { + switch (i) { + case M98088_REG_BIAS_CNTL: + val = 0xf0; + break; + case M98088_REG_DAC_BIAS2: + val = 0x0f; + break; + default: + val = 0; + } + ret = maxim_i2c_write(priv, i, val); + if (ret < 0) { + debug("%s: Failed to reset: %d\n", __func__, ret); + return ret; + } + } + + return 0; +} + +/** + * max98088_device_init() - Initialise max98088 codec device + * + * @priv: max98088 information + * + * @return -EIO for error, 0 for success. + */ +static int max98088_device_init(struct maxim_priv *priv) +{ + unsigned char id; + int error = 0; + + /* reset the codec, the DSP core, and disable all interrupts */ + error = max98088_reset(priv); + if (error != 0) { + debug("Reset\n"); + return error; + } + + /* initialize private data */ + priv->sysclk = -1U; + priv->rate = -1U; + priv->fmt = -1U; + + error = maxim_i2c_read(priv, M98088_REG_REV_ID, &id); + if (error < 0) { + debug("%s: Failure reading hardware revision: %d\n", + __func__, id); + return -EIO; + } + debug("%s: Hardware revision: %d\n", __func__, id); + + return 0; +} + +static int max98088_setup_interface(struct maxim_priv *priv) +{ + int error; + + /* Reading interrupt status to clear them */ + error = maxim_i2c_write(priv, M98088_REG_PWR_SYS, M98088_PWRSV); + error |= maxim_i2c_write(priv, M98088_REG_IRQ_ENABLE, 0x00); + + /* + * initialize registers to hardware default configuring audio + * interface2 to DAI1 + */ + error |= maxim_i2c_write(priv, M98088_REG_MIX_DAC, + M98088_DAI1L_TO_DACL | M98088_DAI1R_TO_DACR); + error |= maxim_i2c_write(priv, M98088_REG_BIAS_CNTL, 0xF0); + error |= maxim_i2c_write(priv, M98088_REG_DAC_BIAS2, 0x0F); + error |= maxim_i2c_write(priv, M98088_REG_DAI1_IOCFG, + M98088_S2NORMAL | M98088_SDATA); + + /* + * route DACL and DACR output to headphone and speakers + * Ordering: DACL, DACR, DACL, DACR + */ + error |= maxim_i2c_write(priv, M98088_REG_MIX_SPK_LEFT, 1); + error |= maxim_i2c_write(priv, M98088_REG_MIX_SPK_RIGHT, 1); + error |= maxim_i2c_write(priv, M98088_REG_MIX_HP_LEFT, 1); + error |= maxim_i2c_write(priv, M98088_REG_MIX_HP_RIGHT, 1); + + /* set volume: -12db */ + error |= maxim_i2c_write(priv, M98088_REG_LVL_SPK_L, 0x0f); + error |= maxim_i2c_write(priv, M98088_REG_LVL_SPK_R, 0x0f); + + /* set volume: -22db */ + error |= maxim_i2c_write(priv, M98088_REG_LVL_HP_L, 0x0d); + error |= maxim_i2c_write(priv, M98088_REG_LVL_HP_R, 0x0d); + + /* power enable */ + error |= maxim_i2c_write(priv, M98088_REG_PWR_EN_OUT, + M98088_HPLEN | M98088_HPREN | M98088_SPLEN | + M98088_SPREN | M98088_DALEN | M98088_DAREN); + if (error < 0) + return -EIO; + + return 0; +} + +static int max98088_do_init(struct maxim_priv *priv, int sampling_rate, + int mclk_freq, int bits_per_sample) +{ + int ret = 0; + + ret = max98088_setup_interface(priv); + if (ret < 0) { + debug("%s: max98088 setup interface failed\n", __func__); + return ret; + } + + ret = max98088_set_sysclk(priv, mclk_freq); + if (ret < 0) { + debug("%s: max98088 codec set sys clock failed\n", __func__); + return ret; + } + + ret = max98088_hw_params(priv, sampling_rate, bits_per_sample); + + if (ret == 0) { + ret = max98088_set_fmt(priv, SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS); + } + + return ret; +} + +static int max98088_set_params(struct udevice *dev, int interface, int rate, + int mclk_freq, int bits_per_sample, + uint channels) +{ + struct maxim_priv *priv = dev_get_priv(dev); + + return max98088_do_init(priv, rate, mclk_freq, bits_per_sample); +} + +static int max98088_probe(struct udevice *dev) +{ + struct maxim_priv *priv = dev_get_priv(dev); + int ret; + + priv->dev = dev; + ret = max98088_device_init(priv); + if (ret < 0) { + debug("%s: max98088 codec chip init failed\n", __func__); + return ret; + } + + return 0; +} + +static const struct audio_codec_ops max98088_ops = { + .set_params = max98088_set_params, +}; + +static const struct udevice_id max98088_ids[] = { + { .compatible = "maxim,max98088" }, + { } +}; + +U_BOOT_DRIVER(max98088) = { + .name = "max98088", + .id = UCLASS_AUDIO_CODEC, + .of_match = max98088_ids, + .probe = max98088_probe, + .ops = &max98088_ops, + .priv_auto_alloc_size = sizeof(struct maxim_priv), +}; diff --git a/drivers/sound/max98088.h b/drivers/sound/max98088.h new file mode 100644 index 0000000000..127d2bda30 --- /dev/null +++ b/drivers/sound/max98088.h @@ -0,0 +1,192 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * max98088.h -- MAX98088 ALSA SoC Audio driver + * + * Copyright 2010 Maxim Integrated Products + */ + +#ifndef _MAX98088_H +#define _MAX98088_H + +/* MAX98088 Registers Definition */ +#define M98088_REG_IRQ_STATUS 0x00 +#define M98088_REG_MIC_STATUS 0x01 +#define M98088_REG_JACK_STAUS 0x02 +#define M98088_REG_BATTERY_VOLTAGE 0x03 +#define M98088_REG_IRQ_ENABLE 0x0f +#define M98088_REG_SYS_CLK 0X10 +#define M98088_REG_DAI1_CLKMODE 0x11 +#define M98088_REG_DAI1_CLKCFG_HI 0x12 +#define M98088_REG_DAI1_CLKCFG_LO 0x13 +#define M98088_REG_DAI1_FORMAT 0x14 +#define M98088_REG_DAI1_CLOCK 0x15 +#define M98088_REG_DAI1_IOCFG 0x16 +#define M98088_REG_DAI1_TDM 0X17 +#define M98088_REG_DAI1_FILTERS 0x18 +#define M98088_REG_DAI2_CLKMODE 0x19 +#define M98088_REG_DAI2_CLKCFG_HI 0x1a +#define M98088_REG_DAI2_CLKCFG_LO 0x1b +#define M98088_REG_DAI2_FORMAT 0x1c +#define M98088_REG_DAI2_CLOCK 0x1d +#define M98088_REG_DAI2_IOCFG 0x1e +#define M98088_REG_DAI2_TDM 0X1f +#define M98088_REG_DAI2_FILTERS 0x20 +#define M98088_REG_SRC 0X21 +#define M98088_REG_MIX_DAC 0X22 +#define M98088_REG_MIX_ADC_LEFT 0x23 +#define M98088_REG_MIX_ADC_RIGHT 0x24 +#define M98088_REG_MIX_HP_LEFT 0x25 +#define M98088_REG_MIX_HP_RIGHT 0x26 +#define M98088_REG_MIX_HP_CNTL 0x27 +#define M98088_REG_MIX_REC_LEFT 0x28 +#define M98088_REG_MIX_REC_RIGHT 0x29 +#define M98088_REG_MIC_REC_CNTL 0x2a +#define M98088_REG_MIX_SPK_LEFT 0x2b +#define M98088_REG_MIX_SPK_RIGHT 0x2c +#define M98088_REG_MIX_SPK_CNTL 0x2d +#define M98088_REG_LVL_SIDETONE 0x2e +#define M98088_REG_LVL_DAI1_PLAY 0x2f +#define M98088_REG_LVL_DAI1_PLAY_EQ 0x30 +#define M98088_REG_LVL_DAI2_PLAY 0x31 +#define M98088_REG_LVL_DAI2_PLAY_EQ 0x32 +#define M98088_REG_LVL_ADC_L 0X33 +#define M98088_REG_LVL_ADC_R 0X34 +#define M98088_REG_LVL_MIC1 0X35 +#define M98088_REG_LVL_MIC2 0X36 +#define M98088_REG_LVL_INA 0X37 +#define M98088_REG_LVL_INB 0X38 +#define M98088_REG_LVL_HP_L 0X39 +#define M98088_REG_LVL_HP_R 0X3a +#define M98088_REG_LVL_REC_L 0X3b +#define M98088_REG_LVL_REC_R 0X3c +#define M98088_REG_LVL_SPK_L 0X3d +#define M98088_REG_LVL_SPK_R 0X3e +#define M98088_REG_MICAGC_CFG 0x3f +#define M98088_REG_MICAGC_THRESH 0x40 +#define M98088_REG_SPKDHP 0X41 +#define M98088_REG_SPKDHP_THRESH 0x42 +#define M98088_REG_SPKALC_COMP 0x43 +#define M98088_REG_PWRLMT_CFG 0x44 +#define M98088_REG_PWRLMT_TIME 0x45 +#define M98088_REG_THDLMT_CFG 0x46 +#define M98088_REG_CFG_AUDIO_IN 0x47 +#define M98088_REG_CFG_MIC 0X48 +#define M98088_REG_CFG_LEVEL 0X49 +#define M98088_REG_CFG_BYPASS 0x4a +#define M98088_REG_CFG_JACKDET 0x4b +#define M98088_REG_PWR_EN_IN 0X4c +#define M98088_REG_PWR_EN_OUT 0x4d +#define M98088_REG_BIAS_CNTL 0X4e +#define M98088_REG_DAC_BIAS1 0X4f +#define M98088_REG_DAC_BIAS2 0X50 +#define M98088_REG_PWR_SYS 0X51 +#define M98088_REG_DAI1_EQ_BASE 0x52 +#define M98088_REG_DAI2_EQ_BASE 0x84 +#define M98088_REG_DAI1_BIQUAD_BASE 0xb6 +#define M98088_REG_DAI2_BIQUAD_BASE 0xc0 +#define M98088_REG_REV_ID 0xff + +#define M98088_REG_CNT (0xff + 1) + +/* MAX98088 Registers Bit Fields */ + +/* M98088_REG_11_DAI1_CLKMODE, M98088_REG_19_DAI2_CLKMODE */ +#define M98088_CLKMODE_MASK 0xFF + +/* M98088_REG_14_DAI1_FORMAT, M98088_REG_1C_DAI2_FORMAT */ +#define M98088_DAI_MAS BIT(7) +#define M98088_DAI_WCI BIT(6) +#define M98088_DAI_BCI BIT(5) +#define M98088_DAI_DLY BIT(4) +#define M98088_DAI_TDM BIT(2) +#define M98088_DAI_FSW BIT(1) +#define M98088_DAI_WS BIT(0) + +/* M98088_REG_15_DAI1_CLOCK, M98088_REG_1D_DAI2_CLOCK */ +#define M98088_DAI_BSEL64 BIT(0) +#define M98088_DAI_OSR64 BIT(6) + +/* M98088_REG_16_DAI1_IOCFG, M98088_REG_1E_DAI2_IOCFG */ +#define M98088_S1NORMAL BIT(6) +#define M98088_S2NORMAL (2 << 6) +#define M98088_SDATA (3 << 0) + +/* M98088_REG_18_DAI1_FILTERS, M98088_REG_20_DAI2_FILTERS */ +#define M98088_DAI_DHF BIT(3) + +/* M98088_REG_22_MIX_DAC */ +#define M98088_DAI1L_TO_DACL BIT(7) +#define M98088_DAI1R_TO_DACL BIT(6) +#define M98088_DAI2L_TO_DACL BIT(5) +#define M98088_DAI2R_TO_DACL BIT(4) +#define M98088_DAI1L_TO_DACR BIT(3) +#define M98088_DAI1R_TO_DACR BIT(2) +#define M98088_DAI2L_TO_DACR BIT(1) +#define M98088_DAI2R_TO_DACR BIT(0) + +/* M98088_REG_2A_MIC_REC_CNTL */ +#define M98088_REC_LINEMODE BIT(7) +#define M98088_REC_LINEMODE_MASK BIT(7) + +/* M98088_REG_2D_MIX_SPK_CNTL */ +#define M98088_MIX_SPKR_GAIN_MASK (3 << 2) +#define M98088_MIX_SPKR_GAIN_SHIFT 2 +#define M98088_MIX_SPKL_GAIN_MASK (3 << 0) +#define M98088_MIX_SPKL_GAIN_SHIFT 0 + +/* M98088_REG_2F_LVL_DAI1_PLAY, M98088_REG_31_LVL_DAI2_PLAY */ +#define M98088_DAI_MUTE BIT(7) +#define M98088_DAI_MUTE_MASK BIT(7) +#define M98088_DAI_VOICE_GAIN_MASK (3 << 4) +#define M98088_DAI_ATTENUATION_MASK (0xf << 0) +#define M98088_DAI_ATTENUATION_SHIFT 0 + +/* M98088_REG_35_LVL_MIC1, M98088_REG_36_LVL_MIC2 */ +#define M98088_MICPRE_MASK (3 << 5) +#define M98088_MICPRE_SHIFT 5 + +/* M98088_REG_3A_LVL_HP_R */ +#define M98088_HP_MUTE BIT(7) + +/* M98088_REG_3C_LVL_REC_R */ +#define M98088_REC_MUTE BIT(7) + +/* M98088_REG_3E_LVL_SPK_R */ +#define M98088_SP_MUTE BIT(7) + +/* M98088_REG_48_CFG_MIC */ +#define M98088_EXTMIC_MASK (3 << 0) +#define M98088_DIGMIC_L BIT(5) +#define M98088_DIGMIC_R BIT(4) + +/* M98088_REG_49_CFG_LEVEL */ +#define M98088_VSEN BIT(6) +#define M98088_ZDEN BIT(5) +#define M98088_EQ2EN BIT(1) +#define M98088_EQ1EN BIT(0) + +/* M98088_REG_4C_PWR_EN_IN */ +#define M98088_INAEN BIT(7) +#define M98088_INBEN BIT(6) +#define M98088_MBEN BIT(3) +#define M98088_ADLEN BIT(1) +#define M98088_ADREN BIT(0) + +/* M98088_REG_4D_PWR_EN_OUT */ +#define M98088_HPLEN BIT(7) +#define M98088_HPREN BIT(6) +#define M98088_HPEN (BIT(7) | BIT(6)) +#define M98088_SPLEN BIT(5) +#define M98088_SPREN BIT(4) +#define M98088_RECEN BIT(3) +#define M98088_DALEN BIT(1) +#define M98088_DAREN BIT(0) + +/* M98088_REG_51_PWR_SYS */ +#define M98088_SHDNRUN BIT(7) +#define M98088_PERFMODE BIT(3) +#define M98088_HPPLYBACK BIT(2) +#define M98088_PWRSV8K BIT(1) +#define M98088_PWRSV BIT(0) + +#endif diff --git a/drivers/sound/max98090.c b/drivers/sound/max98090.c index 346ff5ffbe..5505c35166 100644 --- a/drivers/sound/max98090.c +++ b/drivers/sound/max98090.c @@ -13,10 +13,6 @@ #include <i2s.h> #include <sound.h> #include <asm/gpio.h> -#include <asm/io.h> -#include <asm/arch/clk.h> -#include <asm/arch/cpu.h> -#include <asm/arch/power.h> #include "maxim_codec.h" #include "max98090.h" @@ -240,9 +236,6 @@ int max98090_device_init(struct maxim_priv *priv) unsigned char id; int error = 0; - /* Enable codec clock */ - set_xclkout(); - /* reset the codec, the DSP core, and disable all interrupts */ error = max98090_reset(priv); if (error != 0) { diff --git a/drivers/sound/max98095.c b/drivers/sound/max98095.c index 99c0e996b4..9e08e96670 100644 --- a/drivers/sound/max98095.c +++ b/drivers/sound/max98095.c @@ -15,10 +15,6 @@ #include <i2c.h> #include <sound.h> #include <asm/gpio.h> -#include <asm/io.h> -#include <asm/arch/clk.h> -#include <asm/arch/cpu.h> -#include <asm/arch/power.h> #include "i2s.h" #include "max98095.h" @@ -306,9 +302,6 @@ static int max98095_device_init(struct maxim_priv *priv) unsigned char id; int ret; - /* Enable codec clock */ - set_xclkout(); - /* reset the codec, the DSP core, and disable all interrupts */ ret = max98095_reset(priv); if (ret != 0) { diff --git a/drivers/sound/maxim_codec.c b/drivers/sound/maxim_codec.c index dcaf081988..5480dce108 100644 --- a/drivers/sound/maxim_codec.c +++ b/drivers/sound/maxim_codec.c @@ -12,9 +12,6 @@ #include <sound.h> #include <asm/gpio.h> #include <asm/io.h> -#include <asm/arch/clk.h> -#include <asm/arch/cpu.h> -#include <asm/arch/power.h> #include "maxim_codec.h" /* diff --git a/drivers/sound/samsung-i2s.c b/drivers/sound/samsung-i2s.c index c19e08e7e3..104584073a 100644 --- a/drivers/sound/samsung-i2s.c +++ b/drivers/sound/samsung-i2s.c @@ -24,7 +24,7 @@ /* * Sets the frame size for I2S LR clock * - * @param i2s_reg i2s regiter address + * @param i2s_reg i2s register address * @param rfs Frame Size */ static void i2s_set_lr_framesize(struct i2s_reg *i2s_reg, unsigned int rfs) @@ -54,7 +54,7 @@ static void i2s_set_lr_framesize(struct i2s_reg *i2s_reg, unsigned int rfs) /* * Sets the i2s transfer control * - * @param i2s_reg i2s regiter address + * @param i2s_reg i2s register address * @param on 1 enable tx , 0 disable tx transfer */ static void i2s_txctrl(struct i2s_reg *i2s_reg, int on) @@ -77,7 +77,7 @@ static void i2s_txctrl(struct i2s_reg *i2s_reg, int on) /* * set the bit clock frame size (in multiples of LRCLK) * - * @param i2s_reg i2s regiter address + * @param i2s_reg i2s register address * @param bfs bit Frame Size */ static void i2s_set_bitclk_framesize(struct i2s_reg *i2s_reg, unsigned bfs) @@ -108,7 +108,7 @@ static void i2s_set_bitclk_framesize(struct i2s_reg *i2s_reg, unsigned bfs) /* * flushes the i2stx fifo * - * @param i2s_reg i2s regiter address + * @param i2s_reg i2s register address * @param flush Tx fifo flush command (0x00 - do not flush * 0x80 - flush tx fifo) */ @@ -122,7 +122,7 @@ static void i2s_fifo(struct i2s_reg *i2s_reg, unsigned int flush) /* * Set System Clock direction * - * @param i2s_reg i2s regiter address + * @param i2s_reg i2s register address * @param dir Clock direction * * @return int value 0 for success, -1 in case of error @@ -145,7 +145,7 @@ static int i2s_set_sysclk_dir(struct i2s_reg *i2s_reg, int dir) * Sets I2S Clcok format * * @param fmt i2s clock properties - * @param i2s_reg i2s regiter address + * @param i2s_reg i2s register address * * @return int value 0 for success, -1 in case of error */ @@ -222,7 +222,7 @@ static int i2s_set_fmt(struct i2s_reg *i2s_reg, unsigned int fmt) * Sets the sample width in bits * * @param blc samplewidth (size of sample in bits) - * @param i2s_reg i2s regiter address + * @param i2s_reg i2s register address * * @return int value 0 for success, -1 in case of error */ @@ -294,7 +294,7 @@ int i2s_transfer_tx_data(struct i2s_uc_priv *pi2s_tx, void *data, return 0; } -int i2s_tx_init(struct i2s_uc_priv *pi2s_tx) +static int i2s_tx_init(struct i2s_uc_priv *pi2s_tx) { int ret; struct i2s_reg *i2s_reg = (struct i2s_reg *)pi2s_tx->base_address; diff --git a/drivers/sound/samsung_sound.c b/drivers/sound/samsung_sound.c index 1d711c8732..b6952675bd 100644 --- a/drivers/sound/samsung_sound.c +++ b/drivers/sound/samsung_sound.c @@ -10,6 +10,7 @@ #include <i2s.h> #include <sound.h> #include <asm/gpio.h> +#include <asm/arch/power.h> static int samsung_sound_setup(struct udevice *dev) { @@ -79,6 +80,9 @@ static int samsung_sound_probe(struct udevice *dev) debug("Probed sound '%s' with codec '%s' and i2s '%s'\n", dev->name, uc_priv->codec->name, uc_priv->i2s->name); + /* Enable codec clock */ + set_xclkout(); + return 0; } @@ -89,7 +93,7 @@ static const struct sound_ops samsung_sound_ops = { static const struct udevice_id samsung_sound_ids[] = { { .compatible = "google,snow-audio-max98095" }, - { .compatible = "google,spring-audio-max98095" }, + { .compatible = "google,spring-audio-max98088" }, { .compatible = "samsung,smdk5420-audio-wm8994" }, { .compatible = "google,peach-audio-max98090" }, { } diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 10fd3039aa..115fc4551f 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -88,7 +88,7 @@ config WDT_ASPEED config WDT_BCM6345 bool "BCM6345 watchdog timer support" - depends on WDT && ARCH_BMIPS + depends on WDT && (ARCH_BMIPS || ARCH_BCM6858 || ARCH_BCM63158) help Select this to enable watchdog timer for BCM6345 SoCs. The watchdog timer is stopped when initialized. diff --git a/drivers/watchdog/bcm6345_wdt.c b/drivers/watchdog/bcm6345_wdt.c index e1bd73dfd4..44f5662038 100644 --- a/drivers/watchdog/bcm6345_wdt.c +++ b/drivers/watchdog/bcm6345_wdt.c @@ -32,8 +32,8 @@ static int bcm6345_wdt_reset(struct udevice *dev) { struct bcm6345_wdt_priv *priv = dev_get_priv(dev); - writel_be(WDT_CTL_START1_MASK, priv->regs + WDT_CTL_REG); - writel_be(WDT_CTL_START2_MASK, priv->regs + WDT_CTL_REG); + writel(WDT_CTL_START1_MASK, priv->regs + WDT_CTL_REG); + writel(WDT_CTL_START2_MASK, priv->regs + WDT_CTL_REG); return 0; } @@ -50,7 +50,7 @@ static int bcm6345_wdt_start(struct udevice *dev, u64 timeout, ulong flags) timeout = WDT_VAL_MAX; } - writel_be(timeout, priv->regs + WDT_VAL_REG); + writel(timeout, priv->regs + WDT_VAL_REG); return bcm6345_wdt_reset(dev); } @@ -64,8 +64,8 @@ static int bcm6345_wdt_stop(struct udevice *dev) { struct bcm6345_wdt_priv *priv = dev_get_priv(dev); - writel_be(WDT_CTL_STOP1_MASK, priv->regs + WDT_CTL_REG); - writel_be(WDT_CTL_STOP2_MASK, priv->regs + WDT_CTL_REG); + writel(WDT_CTL_STOP1_MASK, priv->regs + WDT_CTL_REG); + writel(WDT_CTL_STOP2_MASK, priv->regs + WDT_CTL_REG); return 0; } |