Commit 412665b46134f93464c09405e02f08ac9c62526d

Authored by Albert ARIBAUD

Merge branch 'u-boot-samsung/master' into 'u-boot-arm/master'

Showing 26 changed files Side-by-side Diff

... ... @@ -914,6 +914,10 @@
914 914 Bo Shen <voice.shen@atmel.com>
915 915 at91sam9x5ek ARM926EJS (AT91SAM9G15,G25,G35,X25,X35 SoC)
916 916  
  917 +Rajeshwari Shinde <rajeshwari.s@samsung.com>
  918 +
  919 + snow ARM ARMV7 (EXYNOS5250 SoC)
  920 +
917 921 Michal Simek <monstr@monstr.eu>
918 922  
919 923 zynq ARM ARMV7 (Zynq SoC)
arch/arm/cpu/armv7/exynos/power.c
... ... @@ -95,4 +95,49 @@
95 95 if (cpu_is_exynos5())
96 96 exynos5_dp_phy_control(enable);
97 97 }
  98 +
  99 +static void exynos5_set_ps_hold_ctrl(void)
  100 +{
  101 + struct exynos5_power *power =
  102 + (struct exynos5_power *)samsung_get_base_power();
  103 +
  104 + /* Set PS-Hold high */
  105 + setbits_le32(&power->ps_hold_control,
  106 + EXYNOS_PS_HOLD_CONTROL_DATA_HIGH);
  107 +}
  108 +
  109 +void set_ps_hold_ctrl(void)
  110 +{
  111 + if (cpu_is_exynos5())
  112 + exynos5_set_ps_hold_ctrl();
  113 +}
  114 +
  115 +
  116 +static void exynos5_set_xclkout(void)
  117 +{
  118 + struct exynos5_power *power =
  119 + (struct exynos5_power *)samsung_get_base_power();
  120 +
  121 + /* use xxti for xclk out */
  122 + clrsetbits_le32(&power->pmu_debug, PMU_DEBUG_CLKOUT_SEL_MASK,
  123 + PMU_DEBUG_XXTI);
  124 +}
  125 +
  126 +void set_xclkout(void)
  127 +{
  128 + if (cpu_is_exynos5())
  129 + exynos5_set_xclkout();
  130 +}
  131 +
  132 +/* Enables hardware tripping to power off the system when TMU fails */
  133 +void set_hw_thermal_trip(void)
  134 +{
  135 + if (cpu_is_exynos5()) {
  136 + struct exynos5_power *power =
  137 + (struct exynos5_power *)samsung_get_base_power();
  138 +
  139 + /* PS_HOLD_CONTROL register ENABLE_HW_TRIP bit*/
  140 + setbits_le32(&power->ps_hold_control, POWER_ENABLE_HW_TRIP);
  141 + }
  142 +}
arch/arm/dts/exynos5250.dtsi
... ... @@ -151,5 +151,10 @@
151 151 };
152 152 };
153 153  
  154 + tmu@10060000 {
  155 + compatible = "samsung,exynos-tmu";
  156 + reg = <0x10060000 0x10000>;
  157 + };
  158 +
154 159 };
arch/arm/include/asm/arch-exynos/power.h
... ... @@ -857,6 +857,9 @@
857 857  
858 858 void set_usbhost_phy_ctrl(unsigned int enable);
859 859  
  860 +/* Enables hardware tripping to power off the system when TMU fails */
  861 +void set_hw_thermal_trip(void);
  862 +
860 863 #define POWER_USB_HOST_PHY_CTRL_EN (1 << 0)
861 864 #define POWER_USB_HOST_PHY_CTRL_DISABLE (0 << 0)
862 865  
... ... @@ -864,5 +867,26 @@
864 867  
865 868 #define EXYNOS_DP_PHY_ENABLE (1 << 0)
866 869  
  870 +#define EXYNOS_PS_HOLD_CONTROL_DATA_HIGH (1 << 8)
  871 +#define POWER_ENABLE_HW_TRIP (1UL << 31)
  872 +
  873 +/*
  874 + * Set ps_hold data driving value high
  875 + * This enables the machine to stay powered on
  876 + * after the initial power-on condition goes away
  877 + * (e.g. power button).
  878 + */
  879 +void set_ps_hold_ctrl(void);
  880 +
  881 +/* PMU_DEBUG bits [12:8] = 0x1000 selects XXTI clock source */
  882 +#define PMU_DEBUG_XXTI 0x1000
  883 +/* Mask bit[12:8] for xxti clock selection */
  884 +#define PMU_DEBUG_CLKOUT_SEL_MASK 0x1f00
  885 +
  886 +/*
  887 + * Pmu debug is used for xclkout, enable xclkout with
  888 + * source as XXTI
  889 + */
  890 +void set_xclkout(void);
867 891 #endif
arch/arm/include/asm/arch-exynos/spl.h
... ... @@ -78,11 +78,12 @@
78 78 */
79 79 u32 uboot_size;
80 80 enum boot_mode boot_source; /* Boot device */
81   - enum mem_manuf mem_manuf; /* Memory Manufacturer */
82 81 unsigned frequency_mhz; /* Frequency of memory in MHz */
83 82 unsigned arm_freq_mhz; /* ARM Frequency in MHz */
84 83 u32 serial_base; /* Serial base address */
85 84 u32 i2c_base; /* i2c base address */
  85 + u32 board_rev_gpios; /* Board revision GPIOs */
  86 + enum mem_manuf mem_manuf; /* Memory Manufacturer */
86 87 } __attribute__((__packed__));
87 88 #endif
88 89  
arch/arm/include/asm/arch-exynos/tmu.h
  1 +/*
  2 + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  3 + * http://www.samsung.com
  4 + * Akshay Saraswat <akshay.s@samsung.com>
  5 + *
  6 + * EXYNOS - Thermal Management Unit
  7 + *
  8 + * See file CREDITS for list of people who contributed to this
  9 + * project.
  10 + *
  11 + * This program is free software; you can redistribute it and/or modify
  12 + * it under the terms of the GNU General Public License version 2 as
  13 + * published by the Free Software Foundation.
  14 + * You should have received a copy of the GNU General Public License
  15 + * along with this program; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  17 + * MA 02111-1307 USA
  18 + */
  19 +
  20 +#ifndef __ASM_ARCH_TMU_H
  21 +#define __ASM_ARCH_TMU_H
  22 +
  23 +struct exynos5_tmu_reg {
  24 + unsigned triminfo;
  25 + unsigned rsvd1;
  26 + unsigned rsvd2;
  27 + unsigned rsvd3;
  28 + unsigned rsvd4;
  29 + unsigned triminfo_control;
  30 + unsigned rsvd5;
  31 + unsigned rsvd6;
  32 + unsigned tmu_control;
  33 + unsigned rsvd7;
  34 + unsigned tmu_status;
  35 + unsigned sampling_internal;
  36 + unsigned counter_value0;
  37 + unsigned counter_value1;
  38 + unsigned rsvd8;
  39 + unsigned rsvd9;
  40 + unsigned current_temp;
  41 + unsigned rsvd10;
  42 + unsigned rsvd11;
  43 + unsigned rsvd12;
  44 + unsigned threshold_temp_rise;
  45 + unsigned threshold_temp_fall;
  46 + unsigned rsvd13;
  47 + unsigned rsvd14;
  48 + unsigned past_temp3_0;
  49 + unsigned past_temp7_4;
  50 + unsigned past_temp11_8;
  51 + unsigned past_temp15_12;
  52 + unsigned inten;
  53 + unsigned intstat;
  54 + unsigned intclear;
  55 + unsigned rsvd15;
  56 + unsigned emul_con;
  57 +};
  58 +#endif /* __ASM_ARCH_TMU_H */
board/samsung/dts/exynos5250-smdk5250.dts
... ... @@ -66,5 +66,18 @@
66 66 compatible = "maxim,max77686_pmic";
67 67 };
68 68 };
  69 +
  70 + tmu@10060000 {
  71 + samsung,min-temp = <25>;
  72 + samsung,max-temp = <125>;
  73 + samsung,start-warning = <95>;
  74 + samsung,start-tripping = <105>;
  75 + samsung,hw-tripping = <110>;
  76 + samsung,efuse-min-value = <40>;
  77 + samsung,efuse-value = <55>;
  78 + samsung,efuse-max-value = <100>;
  79 + samsung,slope = <274761730>;
  80 + samsung,dc-value = <25>;
  81 + };
69 82 };
board/samsung/dts/exynos5250-snow.dts
  1 +/*
  2 + * SAMSUNG Snow board device tree source
  3 + *
  4 + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  5 + * http://www.samsung.com
  6 + *
  7 + * This program is free software; you can redistribute it and/or modify
  8 + * it under the terms of the GNU General Public License version 2 as
  9 + * published by the Free Software Foundation.
  10 +*/
  11 +
  12 +/dts-v1/;
  13 +/include/ ARCH_CPU_DTS
  14 +
  15 +/ {
  16 + model = "Google Snow";
  17 + compatible = "google,snow", "samsung,exynos5250";
  18 +
  19 + aliases {
  20 + i2c0 = "/i2c@12c60000";
  21 + i2c1 = "/i2c@12c70000";
  22 + i2c2 = "/i2c@12c80000";
  23 + i2c3 = "/i2c@12c90000";
  24 + i2c4 = "/i2c@12ca0000";
  25 + i2c5 = "/i2c@12cb0000";
  26 + i2c6 = "/i2c@12cc0000";
  27 + i2c7 = "/i2c@12cd0000";
  28 + spi0 = "/spi@12d20000";
  29 + spi1 = "/spi@12d30000";
  30 + spi2 = "/spi@12d40000";
  31 + spi3 = "/spi@131a0000";
  32 + spi4 = "/spi@131b0000";
  33 + };
  34 +
  35 + sound@12d60000 {
  36 + samsung,i2s-epll-clock-frequency = <192000000>;
  37 + samsung,i2s-sampling-rate = <48000>;
  38 + samsung,i2s-bits-per-sample = <16>;
  39 + samsung,i2s-channels = <2>;
  40 + samsung,i2s-lr-clk-framesize = <256>;
  41 + samsung,i2s-bit-clk-framesize = <32>;
  42 + samsung,codec-type = "max98095";
  43 + };
  44 +
  45 + i2c@12cd0000 {
  46 + soundcodec@22 {
  47 + reg = <0x22>;
  48 + compatible = "maxim,max98095-codec";
  49 + };
  50 + };
  51 +
  52 + i2c@12c60000 {
  53 + pmic@9 {
  54 + reg = <0x9>;
  55 + compatible = "maxim,max77686_pmic";
  56 + };
  57 + };
  58 +};
board/samsung/smdk5250/smdk5250.c
... ... @@ -23,6 +23,7 @@
23 23 #include <common.h>
24 24 #include <fdtdec.h>
25 25 #include <asm/io.h>
  26 +#include <errno.h>
26 27 #include <i2c.h>
27 28 #include <lcd.h>
28 29 #include <netdev.h>
29 30  
... ... @@ -35,9 +36,40 @@
35 36 #include <asm/arch/sromc.h>
36 37 #include <asm/arch/dp_info.h>
37 38 #include <power/pmic.h>
  39 +#include <power/max77686_pmic.h>
  40 +#include <tmu.h>
38 41  
39 42 DECLARE_GLOBAL_DATA_PTR;
40 43  
  44 +#if defined CONFIG_EXYNOS_TMU
  45 +/*
  46 + * Boot Time Thermal Analysis for SoC temperature threshold breach
  47 + */
  48 +static void boot_temp_check(void)
  49 +{
  50 + int temp;
  51 +
  52 + switch (tmu_monitor(&temp)) {
  53 + /* Status TRIPPED ans WARNING means corresponding threshold breach */
  54 + case TMU_STATUS_TRIPPED:
  55 + puts("EXYNOS_TMU: TRIPPING! Device power going down ...\n");
  56 + set_ps_hold_ctrl();
  57 + hang();
  58 + break;
  59 + case TMU_STATUS_WARNING:
  60 + puts("EXYNOS_TMU: WARNING! Temperature very high\n");
  61 + break;
  62 + /*
  63 + * TMU_STATUS_INIT means something is wrong with temperature sensing
  64 + * and TMU status was changed back from NORMAL to INIT.
  65 + */
  66 + case TMU_STATUS_INIT:
  67 + default:
  68 + debug("EXYNOS_TMU: Unknown TMU state\n");
  69 + }
  70 +}
  71 +#endif
  72 +
41 73 #ifdef CONFIG_USB_EHCI_EXYNOS
42 74 int board_usb_vbus_init(void)
43 75 {
44 76  
45 77  
... ... @@ -54,15 +86,39 @@
54 86 }
55 87 #endif
56 88  
  89 +#ifdef CONFIG_SOUND_MAX98095
  90 +static void board_enable_audio_codec(void)
  91 +{
  92 + struct exynos5_gpio_part1 *gpio1 = (struct exynos5_gpio_part1 *)
  93 + samsung_get_base_gpio_part1();
  94 +
  95 + /* Enable MAX98095 Codec */
  96 + s5p_gpio_direction_output(&gpio1->x1, 7, 1);
  97 + s5p_gpio_set_pull(&gpio1->x1, 7, GPIO_PULL_NONE);
  98 +}
  99 +#endif
  100 +
57 101 int board_init(void)
58 102 {
59 103 gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL);
  104 +
  105 +#if defined CONFIG_EXYNOS_TMU
  106 + if (tmu_init(gd->fdt_blob) != TMU_STATUS_NORMAL) {
  107 + debug("%s: Failed to init TMU\n", __func__);
  108 + return -1;
  109 + }
  110 + boot_temp_check();
  111 +#endif
  112 +
60 113 #ifdef CONFIG_EXYNOS_SPI
61 114 spi_init();
62 115 #endif
63 116 #ifdef CONFIG_USB_EHCI_EXYNOS
64 117 board_usb_vbus_init();
65 118 #endif
  119 +#ifdef CONFIG_SOUND_MAX98095
  120 + board_enable_audio_codec();
  121 +#endif
66 122 return 0;
67 123 }
68 124  
69 125  
70 126  
... ... @@ -80,12 +136,119 @@
80 136 }
81 137  
82 138 #if defined(CONFIG_POWER)
  139 +static int pmic_reg_update(struct pmic *p, int reg, uint regval)
  140 +{
  141 + u32 val;
  142 + int ret = 0;
  143 +
  144 + ret = pmic_reg_read(p, reg, &val);
  145 + if (ret) {
  146 + debug("%s: PMIC %d register read failed\n", __func__, reg);
  147 + return -1;
  148 + }
  149 + val |= regval;
  150 + ret = pmic_reg_write(p, reg, val);
  151 + if (ret) {
  152 + debug("%s: PMIC %d register write failed\n", __func__, reg);
  153 + return -1;
  154 + }
  155 + return 0;
  156 +}
  157 +
83 158 int power_init_board(void)
84 159 {
  160 + struct pmic *p;
  161 +
  162 + set_ps_hold_ctrl();
  163 +
  164 + i2c_init(CONFIG_SYS_I2C_SPEED, CONFIG_SYS_I2C_SLAVE);
  165 +
85 166 if (pmic_init(I2C_PMIC))
86 167 return -1;
87   - else
88   - return 0;
  168 +
  169 + p = pmic_get("MAX77686_PMIC");
  170 + if (!p)
  171 + return -ENODEV;
  172 +
  173 + if (pmic_probe(p))
  174 + return -1;
  175 +
  176 + if (pmic_reg_update(p, MAX77686_REG_PMIC_32KHZ, MAX77686_32KHCP_EN))
  177 + return -1;
  178 +
  179 + if (pmic_reg_update(p, MAX77686_REG_PMIC_BBAT,
  180 + MAX77686_BBCHOSTEN | MAX77686_BBCVS_3_5V))
  181 + return -1;
  182 +
  183 + /* VDD_MIF */
  184 + if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK1OUT,
  185 + MAX77686_BUCK1OUT_1V)) {
  186 + debug("%s: PMIC %d register write failed\n", __func__,
  187 + MAX77686_REG_PMIC_BUCK1OUT);
  188 + return -1;
  189 + }
  190 +
  191 + if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK1CRTL,
  192 + MAX77686_BUCK1CTRL_EN))
  193 + return -1;
  194 +
  195 + /* VDD_ARM */
  196 + if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK2DVS1,
  197 + MAX77686_BUCK2DVS1_1_3V)) {
  198 + debug("%s: PMIC %d register write failed\n", __func__,
  199 + MAX77686_REG_PMIC_BUCK2DVS1);
  200 + return -1;
  201 + }
  202 +
  203 + if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK2CTRL1,
  204 + MAX77686_BUCK2CTRL_ON))
  205 + return -1;
  206 +
  207 + /* VDD_INT */
  208 + if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK3DVS1,
  209 + MAX77686_BUCK3DVS1_1_0125V)) {
  210 + debug("%s: PMIC %d register write failed\n", __func__,
  211 + MAX77686_REG_PMIC_BUCK3DVS1);
  212 + return -1;
  213 + }
  214 +
  215 + if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK3CTRL,
  216 + MAX77686_BUCK3CTRL_ON))
  217 + return -1;
  218 +
  219 + /* VDD_G3D */
  220 + if (pmic_reg_write(p, MAX77686_REG_PMIC_BUCK4DVS1,
  221 + MAX77686_BUCK4DVS1_1_2V)) {
  222 + debug("%s: PMIC %d register write failed\n", __func__,
  223 + MAX77686_REG_PMIC_BUCK4DVS1);
  224 + return -1;
  225 + }
  226 +
  227 + if (pmic_reg_update(p, MAX77686_REG_PMIC_BUCK4CTRL1,
  228 + MAX77686_BUCK3CTRL_ON))
  229 + return -1;
  230 +
  231 + /* VDD_LDO2 */
  232 + if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO2CTRL1,
  233 + MAX77686_LD02CTRL1_1_5V | EN_LDO))
  234 + return -1;
  235 +
  236 + /* VDD_LDO3 */
  237 + if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO3CTRL1,
  238 + MAX77686_LD03CTRL1_1_8V | EN_LDO))
  239 + return -1;
  240 +
  241 + /* VDD_LDO5 */
  242 + if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO5CTRL1,
  243 + MAX77686_LD05CTRL1_1_8V | EN_LDO))
  244 + return -1;
  245 +
  246 + /* VDD_LDO10 */
  247 + if (pmic_reg_update(p, MAX77686_REG_PMIC_LDO10CTRL1,
  248 + MAX77686_LD10CTRL1_1_8V | EN_LDO))
  249 + return -1;
  250 +
  251 + return 0;
89 252 }
90 253 #endif
91 254  
92 255  
... ... @@ -212,8 +375,17 @@
212 375 #ifdef CONFIG_DISPLAY_BOARDINFO
213 376 int checkboard(void)
214 377 {
215   - printf("\nBoard: SMDK5250\n");
  378 +#ifdef CONFIG_OF_CONTROL
  379 + const char *board_name;
216 380  
  381 + board_name = fdt_getprop(gd->fdt_blob, 0, "model", NULL);
  382 + if (board_name == NULL)
  383 + printf("\nUnknown Board\n");
  384 + else
  385 + printf("\nBoard: %s\n", board_name);
  386 +#else
  387 + printf("\nBoard: SMDK5250\n");
  388 +#endif
217 389 return 0;
218 390 }
219 391 #endif
... ... @@ -298,6 +298,7 @@
298 298 smdkc100 arm armv7 smdkc100 samsung s5pc1xx
299 299 origen arm armv7 origen samsung exynos
300 300 s5pc210_universal arm armv7 universal_c210 samsung exynos
  301 +snow arm armv7 smdk5250 samsung exynos
301 302 smdk5250 arm armv7 smdk5250 samsung exynos
302 303 smdkv310 arm armv7 smdkv310 samsung exynos
303 304 trats arm armv7 trats samsung exynos
... ... @@ -27,7 +27,9 @@
27 27  
28 28 #include <dtt.h>
29 29 #include <i2c.h>
  30 +#include <tmu.h>
30 31  
  32 +#if defined CONFIG_DTT_SENSORS
31 33 static unsigned long sensor_initialized;
32 34  
33 35 static void _initialize_dtt(void)
34 36  
35 37  
... ... @@ -59,9 +61,11 @@
59 61 /* switch back to original I2C bus */
60 62 I2C_SET_BUS(old_bus);
61 63 }
  64 +#endif
62 65  
63   -int do_dtt (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
  66 +int dtt_i2c(void)
64 67 {
  68 +#if defined CONFIG_DTT_SENSORS
65 69 int i;
66 70 unsigned char sensors[] = CONFIG_DTT_SENSORS;
67 71 int old_bus;
68 72  
... ... @@ -83,8 +87,34 @@
83 87  
84 88 /* switch back to original I2C bus */
85 89 I2C_SET_BUS(old_bus);
  90 +#endif
86 91  
87 92 return 0;
  93 +}
  94 +
  95 +int dtt_tmu(void)
  96 +{
  97 +#if defined CONFIG_TMU_CMD_DTT
  98 + int cur_temp;
  99 +
  100 + /* Sense and return latest thermal info */
  101 + if (tmu_monitor(&cur_temp) == TMU_STATUS_INIT) {
  102 + puts("TMU is in unknown state, temperature is invalid\n");
  103 + return -1;
  104 + }
  105 + printf("Current temperature: %u degrees Celsius\n", cur_temp);
  106 +#endif
  107 + return 0;
  108 +}
  109 +
  110 +int do_dtt(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
  111 +{
  112 + int err = 0;
  113 +
  114 + err |= dtt_i2c();
  115 + err |= dtt_tmu();
  116 +
  117 + return err;
88 118 } /* do_dtt() */
89 119  
90 120 /***************************************************/
doc/device-tree-bindings/exynos/tmu.txt
  1 +Exynos Thermal management Unit
  2 +
  3 +Required properties:
  4 +
  5 + - compatible : Should be "samsung,exynos-tmu" for TMU
  6 + - samsung,min-temp : Minimum temperature value (25 degree celsius)
  7 + - Current temperature of SoC should be more than this value.
  8 + - samsung,max-temp : Maximum temperature value (125 degree celsius)
  9 + - Current temperature of SoC should be less than this value.
  10 + - samsung,start-warning : Temperature at which TMU starts giving warning (degree celsius)
  11 + - samsung,start-tripping : Temperature at which TMU shuts down the system (degree celsius)
  12 + - samsung,hw-tripping : Temperature at which hardware tripping should happen
  13 + in case TMU fails to power off (degree celsius)
  14 + - samsung,efuse-min-value : SOC efuse min value (Constant 40)
  15 + - efuse-value should be more than this value.
  16 + - samsung,efuse-value : SOC actual efuse value (Literal value)
  17 + - This is the data trimming info.
  18 + - This value is used to calculate measuring error.
  19 + - samsung,efuse-max-value : SoC max efuse value (Constant 100)
  20 + - efuse-value should be less than this value.
  21 + - samsung,slope : Default value 274761730 (Constant 0x1060_8802).
  22 + - This is the default value for TMU_CONTROL register.
  23 + - It sets the gain of amplifier to the positive-tc generator block.
  24 + - It selects thermal tripping mode and enables thermal tripping.
  25 + - samsung,dc-value : Measured data calibration value (Constant 25)
  26 + - Used for tempearture calculation.
  27 + - This is 25 because temperature measured is always above 25 degrees.
  28 +
  29 +
  30 +Example:
  31 +
  32 +tmu@10060000 {
  33 + compatible = "samsung,exynos-tmu"
  34 + samsung,min-temp = <25>;
  35 + samsung,max-temp = <125>;
  36 + samsung,start-warning = <95>;
  37 + samsung,start-tripping = <105>;
  38 + samsung,hw-tripping = <110>;
  39 + samsung,efuse-min-value = <40>;
  40 + samsung,efuse-value = <55>;
  41 + samsung,efuse-max-value = <100>;
  42 + samsung,slope = <274761730>;
  43 + samsung,dc-value = <25>;
  44 +};
... ... @@ -412,9 +412,11 @@
412 412 status = sdhci_readl(host, SDHCI_PRESENT_STATE);
413 413 }
414 414  
415   - /* Eable all state */
416   - sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_INT_ENABLE);
417   - sdhci_writel(host, SDHCI_INT_ALL_MASK, SDHCI_SIGNAL_ENABLE);
  415 + /* Enable only interrupts served by the SD controller */
  416 + sdhci_writel(host, SDHCI_INT_DATA_MASK | SDHCI_INT_CMD_MASK
  417 + , SDHCI_INT_ENABLE);
  418 + /* Mask all sdhci interrupt sources */
  419 + sdhci_writel(host, 0x0, SDHCI_SIGNAL_ENABLE);
418 420  
419 421 return 0;
420 422 }
drivers/power/Makefile
... ... @@ -25,6 +25,7 @@
25 25  
26 26 LIB := $(obj)libpower.o
27 27  
  28 +COBJS-$(CONFIG_EXYNOS_TMU) += exynos-tmu.o
28 29 COBJS-$(CONFIG_FTPMU010_POWER) += ftpmu010.o
29 30 COBJS-$(CONFIG_TPS6586X_POWER) += tps6586x.o
30 31 COBJS-$(CONFIG_TWL4030_POWER) += twl4030.o
drivers/power/exynos-tmu.c
  1 +/*
  2 + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  3 + * http://www.samsung.com
  4 + * Akshay Saraswat <akshay.s@samsung.com>
  5 + *
  6 + * EXYNOS - Thermal Management Unit
  7 + *
  8 + * See file CREDITS for list of people who contributed to this
  9 + * project.
  10 + *
  11 + * This program is free software; you can redistribute it and/or modify
  12 + * it under the terms of the GNU General Public License version 2 as
  13 + * published by the Free Software Foundation.
  14 + * You should have received a copy of the GNU General Public License
  15 + * along with this program; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  17 + * MA 02111-1307 USA
  18 + */
  19 +
  20 +#include <common.h>
  21 +#include <errno.h>
  22 +#include <fdtdec.h>
  23 +#include <tmu.h>
  24 +#include <asm/arch/tmu.h>
  25 +#include <asm/arch/power.h>
  26 +
  27 +#define TRIMINFO_RELOAD 1
  28 +#define CORE_EN 1
  29 +#define THERM_TRIP_EN (1 << 12)
  30 +
  31 +#define INTEN_RISE0 1
  32 +#define INTEN_RISE1 (1 << 4)
  33 +#define INTEN_RISE2 (1 << 8)
  34 +#define INTEN_FALL0 (1 << 16)
  35 +#define INTEN_FALL1 (1 << 20)
  36 +#define INTEN_FALL2 (1 << 24)
  37 +
  38 +#define TRIM_INFO_MASK 0xff
  39 +
  40 +#define INTCLEAR_RISE0 1
  41 +#define INTCLEAR_RISE1 (1 << 4)
  42 +#define INTCLEAR_RISE2 (1 << 8)
  43 +#define INTCLEAR_FALL0 (1 << 16)
  44 +#define INTCLEAR_FALL1 (1 << 20)
  45 +#define INTCLEAR_FALL2 (1 << 24)
  46 +#define INTCLEARALL (INTCLEAR_RISE0 | INTCLEAR_RISE1 | \
  47 + INTCLEAR_RISE2 | INTCLEAR_FALL0 | \
  48 + INTCLEAR_FALL1 | INTCLEAR_FALL2)
  49 +
  50 +/* Tmeperature threshold values for various thermal events */
  51 +struct temperature_params {
  52 + /* minimum value in temperature code range */
  53 + unsigned int min_val;
  54 + /* maximum value in temperature code range */
  55 + unsigned int max_val;
  56 + /* temperature threshold to start warning */
  57 + unsigned int start_warning;
  58 + /* temperature threshold CPU tripping */
  59 + unsigned int start_tripping;
  60 + /* temperature threshold for HW tripping */
  61 + unsigned int hardware_tripping;
  62 +};
  63 +
  64 +/* Pre-defined values and thresholds for calibration of current temperature */
  65 +struct tmu_data {
  66 + /* pre-defined temperature thresholds */
  67 + struct temperature_params ts;
  68 + /* pre-defined efuse range minimum value */
  69 + unsigned int efuse_min_value;
  70 + /* pre-defined efuse value for temperature calibration */
  71 + unsigned int efuse_value;
  72 + /* pre-defined efuse range maximum value */
  73 + unsigned int efuse_max_value;
  74 + /* current temperature sensing slope */
  75 + unsigned int slope;
  76 +};
  77 +
  78 +/* TMU device specific details and status */
  79 +struct tmu_info {
  80 + /* base Address for the TMU */
  81 + unsigned tmu_base;
  82 + /* pre-defined values for calibration and thresholds */
  83 + struct tmu_data data;
  84 + /* value required for triminfo_25 calibration */
  85 + unsigned int te1;
  86 + /* value required for triminfo_85 calibration */
  87 + unsigned int te2;
  88 + /* Value for measured data calibration */
  89 + int dc_value;
  90 + /* enum value indicating status of the TMU */
  91 + int tmu_state;
  92 +};
  93 +
  94 +/* Global struct tmu_info variable to store init values */
  95 +static struct tmu_info gbl_info;
  96 +
  97 +/*
  98 + * Get current temperature code from register,
  99 + * then calculate and calibrate it's value
  100 + * in degree celsius.
  101 + *
  102 + * @return current temperature of the chip as sensed by TMU
  103 + */
  104 +static int get_cur_temp(struct tmu_info *info)
  105 +{
  106 + int cur_temp;
  107 + struct exynos5_tmu_reg *reg = (struct exynos5_tmu_reg *)info->tmu_base;
  108 +
  109 + /*
  110 + * Temperature code range between min 25 and max 125.
  111 + * May run more than once for first call as initial sensing
  112 + * has not yet happened.
  113 + */
  114 + do {
  115 + cur_temp = readl(&reg->current_temp) & 0xff;
  116 + } while (cur_temp == 0 && info->tmu_state == TMU_STATUS_NORMAL);
  117 +
  118 + /* Calibrate current temperature */
  119 + cur_temp = cur_temp - info->te1 + info->dc_value;
  120 +
  121 + return cur_temp;
  122 +}
  123 +
  124 +/*
  125 + * Monitors status of the TMU device and exynos temperature
  126 + *
  127 + * @param temp pointer to the current temperature value
  128 + * @return enum tmu_status_t value, code indicating event to execute
  129 + */
  130 +enum tmu_status_t tmu_monitor(int *temp)
  131 +{
  132 + int cur_temp;
  133 + struct tmu_data *data = &gbl_info.data;
  134 +
  135 + if (gbl_info.tmu_state == TMU_STATUS_INIT)
  136 + return TMU_STATUS_INIT;
  137 +
  138 + /* Read current temperature of the SOC */
  139 + cur_temp = get_cur_temp(&gbl_info);
  140 + *temp = cur_temp;
  141 +
  142 + /* Temperature code lies between min 25 and max 125 */
  143 + if (cur_temp >= data->ts.start_tripping &&
  144 + cur_temp <= data->ts.max_val) {
  145 + return TMU_STATUS_TRIPPED;
  146 + } else if (cur_temp >= data->ts.start_warning) {
  147 + return TMU_STATUS_WARNING;
  148 + } else if (cur_temp < data->ts.start_warning &&
  149 + cur_temp >= data->ts.min_val) {
  150 + return TMU_STATUS_NORMAL;
  151 + } else {
  152 + /* Temperature code does not lie between min 25 and max 125 */
  153 + gbl_info.tmu_state = TMU_STATUS_INIT;
  154 + debug("EXYNOS_TMU: Thermal reading failed\n");
  155 + return TMU_STATUS_INIT;
  156 + }
  157 +}
  158 +
  159 +/*
  160 + * Get TMU specific pre-defined values from FDT
  161 + *
  162 + * @param info pointer to the tmu_info struct
  163 + * @param blob FDT blob
  164 + * @return int value, 0 for success
  165 + */
  166 +static int get_tmu_fdt_values(struct tmu_info *info, const void *blob)
  167 +{
  168 +#ifdef CONFIG_OF_CONTROL
  169 + int node;
  170 + int error = 0;
  171 +
  172 + /* Get the node from FDT for TMU */
  173 + node = fdtdec_next_compatible(blob, 0,
  174 + COMPAT_SAMSUNG_EXYNOS_TMU);
  175 + if (node < 0) {
  176 + debug("EXYNOS_TMU: No node for tmu in device tree\n");
  177 + return -1;
  178 + }
  179 +
  180 + /*
  181 + * Get the pre-defined TMU specific values from FDT.
  182 + * All of these are expected to be correct otherwise
  183 + * miscalculation of register values in tmu_setup_parameters
  184 + * may result in misleading current temperature.
  185 + */
  186 + info->tmu_base = fdtdec_get_addr(blob, node, "reg");
  187 + if (info->tmu_base == FDT_ADDR_T_NONE) {
  188 + debug("%s: Missing tmu-base\n", __func__);
  189 + return -1;
  190 + }
  191 + info->data.ts.min_val = fdtdec_get_int(blob,
  192 + node, "samsung,min-temp", -1);
  193 + error |= info->data.ts.min_val;
  194 + info->data.ts.max_val = fdtdec_get_int(blob,
  195 + node, "samsung,max-temp", -1);
  196 + error |= info->data.ts.max_val;
  197 + info->data.ts.start_warning = fdtdec_get_int(blob,
  198 + node, "samsung,start-warning", -1);
  199 + error |= info->data.ts.start_warning;
  200 + info->data.ts.start_tripping = fdtdec_get_int(blob,
  201 + node, "samsung,start-tripping", -1);
  202 + error |= info->data.ts.start_tripping;
  203 + info->data.ts.hardware_tripping = fdtdec_get_int(blob,
  204 + node, "samsung,hw-tripping", -1);
  205 + error |= info->data.ts.hardware_tripping;
  206 + info->data.efuse_min_value = fdtdec_get_int(blob,
  207 + node, "samsung,efuse-min-value", -1);
  208 + error |= info->data.efuse_min_value;
  209 + info->data.efuse_value = fdtdec_get_int(blob,
  210 + node, "samsung,efuse-value", -1);
  211 + error |= info->data.efuse_value;
  212 + info->data.efuse_max_value = fdtdec_get_int(blob,
  213 + node, "samsung,efuse-max-value", -1);
  214 + error |= info->data.efuse_max_value;
  215 + info->data.slope = fdtdec_get_int(blob,
  216 + node, "samsung,slope", -1);
  217 + error |= info->data.slope;
  218 + info->dc_value = fdtdec_get_int(blob,
  219 + node, "samsung,dc-value", -1);
  220 + error |= info->dc_value;
  221 +
  222 + if (error == -1) {
  223 + debug("fail to get tmu node properties\n");
  224 + return -1;
  225 + }
  226 +#endif
  227 +
  228 + return 0;
  229 +}
  230 +
  231 +/*
  232 + * Calibrate and calculate threshold values and
  233 + * enable interrupt levels
  234 + *
  235 + * @param info pointer to the tmu_info struct
  236 + */
  237 +static void tmu_setup_parameters(struct tmu_info *info)
  238 +{
  239 + unsigned int te_code, con;
  240 + unsigned int warning_code, trip_code, hwtrip_code;
  241 + unsigned int cooling_temp;
  242 + unsigned int rising_value;
  243 + struct tmu_data *data = &info->data;
  244 + struct exynos5_tmu_reg *reg = (struct exynos5_tmu_reg *)info->tmu_base;
  245 +
  246 + /* Must reload for reading efuse value from triminfo register */
  247 + writel(TRIMINFO_RELOAD, &reg->triminfo_control);
  248 +
  249 + /* Get the compensation parameter */
  250 + te_code = readl(&reg->triminfo);
  251 + info->te1 = te_code & TRIM_INFO_MASK;
  252 + info->te2 = ((te_code >> 8) & TRIM_INFO_MASK);
  253 +
  254 + if ((data->efuse_min_value > info->te1) ||
  255 + (info->te1 > data->efuse_max_value)
  256 + || (info->te2 != 0))
  257 + info->te1 = data->efuse_value;
  258 +
  259 + /* Get RISING & FALLING Threshold value */
  260 + warning_code = data->ts.start_warning
  261 + + info->te1 - info->dc_value;
  262 + trip_code = data->ts.start_tripping
  263 + + info->te1 - info->dc_value;
  264 + hwtrip_code = data->ts.hardware_tripping
  265 + + info->te1 - info->dc_value;
  266 +
  267 + cooling_temp = 0;
  268 +
  269 + rising_value = ((warning_code << 8) |
  270 + (trip_code << 16) |
  271 + (hwtrip_code << 24));
  272 +
  273 + /* Set interrupt level */
  274 + writel(rising_value, &reg->threshold_temp_rise);
  275 + writel(cooling_temp, &reg->threshold_temp_fall);
  276 +
  277 + /*
  278 + * Init TMU control tuning parameters
  279 + * [28:24] VREF - Voltage reference
  280 + * [15:13] THERM_TRIP_MODE - Tripping mode
  281 + * [12] THERM_TRIP_EN - Thermal tripping enable
  282 + * [11:8] BUF_SLOPE_SEL - Gain of amplifier
  283 + * [6] THERM_TRIP_BY_TQ_EN - Tripping by TQ pin
  284 + */
  285 + writel(data->slope, &reg->tmu_control);
  286 +
  287 + writel(INTCLEARALL, &reg->intclear);
  288 +
  289 + /* TMU core enable */
  290 + con = readl(&reg->tmu_control);
  291 + con |= THERM_TRIP_EN | CORE_EN;
  292 +
  293 + writel(con, &reg->tmu_control);
  294 +
  295 + /* Enable HW thermal trip */
  296 + set_hw_thermal_trip();
  297 +
  298 + /* LEV1 LEV2 interrupt enable */
  299 + writel(INTEN_RISE1 | INTEN_RISE2, &reg->inten);
  300 +}
  301 +
  302 +/*
  303 + * Initialize TMU device
  304 + *
  305 + * @param blob FDT blob
  306 + * @return int value, 0 for success
  307 + */
  308 +int tmu_init(const void *blob)
  309 +{
  310 + gbl_info.tmu_state = TMU_STATUS_INIT;
  311 + if (get_tmu_fdt_values(&gbl_info, blob) < 0)
  312 + goto ret;
  313 +
  314 + tmu_setup_parameters(&gbl_info);
  315 + gbl_info.tmu_state = TMU_STATUS_NORMAL;
  316 +ret:
  317 +
  318 + return gbl_info.tmu_state;
  319 +}
drivers/sound/Makefile
... ... @@ -28,6 +28,7 @@
28 28 COBJS-$(CONFIG_SOUND) += sound.o
29 29 COBJS-$(CONFIG_I2S) += samsung-i2s.o
30 30 COBJS-$(CONFIG_SOUND_WM8994) += wm8994.o
  31 +COBJS-$(CONFIG_SOUND_MAX98095) += max98095.o
31 32  
32 33 COBJS := $(COBJS-y)
33 34 SRCS := $(COBJS:.o=.c)
drivers/sound/max98095.c
  1 +/*
  2 + * max98095.c -- MAX98095 ALSA SoC Audio driver
  3 + *
  4 + * Copyright 2011 Maxim Integrated Products
  5 + *
  6 + * Modified for uboot by R. Chandrasekar (rcsekar@samsung.com)
  7 + *
  8 + * This program is free software; you can redistribute it and/or modify
  9 + * it under the terms of the GNU General Public License version 2 as
  10 + * published by the Free Software Foundation.
  11 + */
  12 +#include <asm/arch/clk.h>
  13 +#include <asm/arch/cpu.h>
  14 +#include <asm/arch/power.h>
  15 +#include <asm/gpio.h>
  16 +#include <asm/io.h>
  17 +#include <common.h>
  18 +#include <div64.h>
  19 +#include <fdtdec.h>
  20 +#include <i2c.h>
  21 +#include <sound.h>
  22 +#include "i2s.h"
  23 +#include "max98095.h"
  24 +
  25 +enum max98095_type {
  26 + MAX98095,
  27 +};
  28 +
  29 +struct max98095_priv {
  30 + enum max98095_type devtype;
  31 + unsigned int sysclk;
  32 + unsigned int rate;
  33 + unsigned int fmt;
  34 +};
  35 +
  36 +static struct sound_codec_info g_codec_info;
  37 +struct max98095_priv g_max98095_info;
  38 +unsigned int g_max98095_i2c_dev_addr;
  39 +
  40 +/* Index 0 is reserved. */
  41 +int rate_table[] = {0, 8000, 11025, 16000, 22050, 24000, 32000, 44100, 48000,
  42 + 88200, 96000};
  43 +
  44 +/*
  45 + * Writes value to a device register through i2c
  46 + *
  47 + * @param reg reg number to be write
  48 + * @param data data to be writen to the above registor
  49 + *
  50 + * @return int value 1 for change, 0 for no change or negative error code.
  51 + */
  52 +static int max98095_i2c_write(unsigned int reg, unsigned char data)
  53 +{
  54 + debug("%s: Write Addr : 0x%02X, Data : 0x%02X\n",
  55 + __func__, reg, data);
  56 + return i2c_write(g_max98095_i2c_dev_addr, reg, 1, &data, 1);
  57 +}
  58 +
  59 +/*
  60 + * Read a value from a device register through i2c
  61 + *
  62 + * @param reg reg number to be read
  63 + * @param data address of read data to be stored
  64 + *
  65 + * @return int value 0 for success, -1 in case of error.
  66 + */
  67 +static unsigned int max98095_i2c_read(unsigned int reg, unsigned char *data)
  68 +{
  69 + int ret;
  70 +
  71 + ret = i2c_read(g_max98095_i2c_dev_addr, reg, 1, data, 1);
  72 + if (ret != 0) {
  73 + debug("%s: Error while reading register %#04x\n",
  74 + __func__, reg);
  75 + return -1;
  76 + }
  77 +
  78 + return 0;
  79 +}
  80 +
  81 +/*
  82 + * update device register bits through i2c
  83 + *
  84 + * @param reg codec register
  85 + * @param mask register mask
  86 + * @param value new value
  87 + *
  88 + * @return int value 0 for success, non-zero error code.
  89 + */
  90 +static int max98095_update_bits(unsigned int reg, unsigned char mask,
  91 + unsigned char value)
  92 +{
  93 + int change, ret = 0;
  94 + unsigned char old, new;
  95 +
  96 + if (max98095_i2c_read(reg, &old) != 0)
  97 + return -1;
  98 + new = (old & ~mask) | (value & mask);
  99 + change = (old != new) ? 1 : 0;
  100 + if (change)
  101 + ret = max98095_i2c_write(reg, new);
  102 + if (ret < 0)
  103 + return ret;
  104 +
  105 + return change;
  106 +}
  107 +
  108 +/*
  109 + * codec mclk clock divider coefficients based on sampling rate
  110 + *
  111 + * @param rate sampling rate
  112 + * @param value address of indexvalue to be stored
  113 + *
  114 + * @return 0 for success or negative error code.
  115 + */
  116 +static int rate_value(int rate, u8 *value)
  117 +{
  118 + int i;
  119 +
  120 + for (i = 1; i < ARRAY_SIZE(rate_table); i++) {
  121 + if (rate_table[i] >= rate) {
  122 + *value = i;
  123 + return 0;
  124 + }
  125 + }
  126 + *value = 1;
  127 +
  128 + return -1;
  129 +}
  130 +
  131 +/*
  132 + * Sets hw params for max98095
  133 + *
  134 + * @param max98095 max98095 information pointer
  135 + * @param rate Sampling rate
  136 + * @param bits_per_sample Bits per sample
  137 + *
  138 + * @return -1 for error and 0 Success.
  139 + */
  140 +static int max98095_hw_params(struct max98095_priv *max98095,
  141 + unsigned int rate, unsigned int bits_per_sample)
  142 +{
  143 + u8 regval;
  144 + int error;
  145 +
  146 + switch (bits_per_sample) {
  147 + case 16:
  148 + error = max98095_update_bits(M98095_034_DAI2_FORMAT,
  149 + M98095_DAI_WS, 0);
  150 + break;
  151 + case 24:
  152 + error = max98095_update_bits(M98095_034_DAI2_FORMAT,
  153 + M98095_DAI_WS, M98095_DAI_WS);
  154 + break;
  155 + default:
  156 + debug("%s: Illegal bits per sample %d.\n",
  157 + __func__, bits_per_sample);
  158 + return -1;
  159 + }
  160 +
  161 + if (rate_value(rate, &regval)) {
  162 + debug("%s: Failed to set sample rate to %d.\n",
  163 + __func__, rate);
  164 + return -1;
  165 + }
  166 + max98095->rate = rate;
  167 +
  168 + error |= max98095_update_bits(M98095_031_DAI2_CLKMODE,
  169 + M98095_CLKMODE_MASK, regval);
  170 +
  171 + /* Update sample rate mode */
  172 + if (rate < 50000)
  173 + error |= max98095_update_bits(M98095_038_DAI2_FILTERS,
  174 + M98095_DAI_DHF, 0);
  175 + else
  176 + error |= max98095_update_bits(M98095_038_DAI2_FILTERS,
  177 + M98095_DAI_DHF, M98095_DAI_DHF);
  178 +
  179 + if (error < 0) {
  180 + debug("%s: Error setting hardware params.\n", __func__);
  181 + return -1;
  182 + }
  183 +
  184 + return 0;
  185 +}
  186 +
  187 +/*
  188 + * Configures Audio interface system clock for the given frequency
  189 + *
  190 + * @param max98095 max98095 information
  191 + * @param freq Sampling frequency in Hz
  192 + *
  193 + * @return -1 for error and 0 success.
  194 + */
  195 +static int max98095_set_sysclk(struct max98095_priv *max98095,
  196 + unsigned int freq)
  197 +{
  198 + int error = 0;
  199 +
  200 + /* Requested clock frequency is already setup */
  201 + if (freq == max98095->sysclk)
  202 + return 0;
  203 +
  204 + /* Setup clocks for slave mode, and using the PLL
  205 + * PSCLK = 0x01 (when master clk is 10MHz to 20MHz)
  206 + * 0x02 (when master clk is 20MHz to 40MHz)..
  207 + * 0x03 (when master clk is 40MHz to 60MHz)..
  208 + */
  209 + if ((freq >= 10000000) && (freq < 20000000)) {
  210 + error = max98095_i2c_write(M98095_026_SYS_CLK, 0x10);
  211 + } else if ((freq >= 20000000) && (freq < 40000000)) {
  212 + error = max98095_i2c_write(M98095_026_SYS_CLK, 0x20);
  213 + } else if ((freq >= 40000000) && (freq < 60000000)) {
  214 + error = max98095_i2c_write(M98095_026_SYS_CLK, 0x30);
  215 + } else {
  216 + debug("%s: Invalid master clock frequency\n", __func__);
  217 + return -1;
  218 + }
  219 +
  220 + debug("%s: Clock at %uHz\n", __func__, freq);
  221 +
  222 + if (error < 0)
  223 + return -1;
  224 +
  225 + max98095->sysclk = freq;
  226 + return 0;
  227 +}
  228 +
  229 +/*
  230 + * Sets Max98095 I2S format
  231 + *
  232 + * @param max98095 max98095 information
  233 + * @param fmt i2S format - supports a subset of the options defined
  234 + * in i2s.h.
  235 + *
  236 + * @return -1 for error and 0 Success.
  237 + */
  238 +static int max98095_set_fmt(struct max98095_priv *max98095, int fmt)
  239 +{
  240 + u8 regval = 0;
  241 + int error = 0;
  242 +
  243 + if (fmt == max98095->fmt)
  244 + return 0;
  245 +
  246 + max98095->fmt = fmt;
  247 +
  248 + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
  249 + case SND_SOC_DAIFMT_CBS_CFS:
  250 + /* Slave mode PLL */
  251 + error |= max98095_i2c_write(M98095_032_DAI2_CLKCFG_HI,
  252 + 0x80);
  253 + error |= max98095_i2c_write(M98095_033_DAI2_CLKCFG_LO,
  254 + 0x00);
  255 + break;
  256 + case SND_SOC_DAIFMT_CBM_CFM:
  257 + /* Set to master mode */
  258 + regval |= M98095_DAI_MAS;
  259 + break;
  260 + case SND_SOC_DAIFMT_CBS_CFM:
  261 + case SND_SOC_DAIFMT_CBM_CFS:
  262 + default:
  263 + debug("%s: Clock mode unsupported\n", __func__);
  264 + return -1;
  265 + }
  266 +
  267 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
  268 + case SND_SOC_DAIFMT_I2S:
  269 + regval |= M98095_DAI_DLY;
  270 + break;
  271 + case SND_SOC_DAIFMT_LEFT_J:
  272 + break;
  273 + default:
  274 + debug("%s: Unrecognized format.\n", __func__);
  275 + return -1;
  276 + }
  277 +
  278 + switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
  279 + case SND_SOC_DAIFMT_NB_NF:
  280 + break;
  281 + case SND_SOC_DAIFMT_NB_IF:
  282 + regval |= M98095_DAI_WCI;
  283 + break;
  284 + case SND_SOC_DAIFMT_IB_NF:
  285 + regval |= M98095_DAI_BCI;
  286 + break;
  287 + case SND_SOC_DAIFMT_IB_IF:
  288 + regval |= M98095_DAI_BCI | M98095_DAI_WCI;
  289 + break;
  290 + default:
  291 + debug("%s: Unrecognized inversion settings.\n", __func__);
  292 + return -1;
  293 + }
  294 +
  295 + error |= max98095_update_bits(M98095_034_DAI2_FORMAT,
  296 + M98095_DAI_MAS | M98095_DAI_DLY | M98095_DAI_BCI |
  297 + M98095_DAI_WCI, regval);
  298 +
  299 + error |= max98095_i2c_write(M98095_035_DAI2_CLOCK,
  300 + M98095_DAI_BSEL64);
  301 +
  302 + if (error < 0) {
  303 + debug("%s: Error setting i2s format.\n", __func__);
  304 + return -1;
  305 + }
  306 +
  307 + return 0;
  308 +}
  309 +
  310 +/*
  311 + * resets the audio codec
  312 + *
  313 + * @return -1 for error and 0 success.
  314 + */
  315 +static int max98095_reset(void)
  316 +{
  317 + int i, ret;
  318 +
  319 + /*
  320 + * Gracefully reset the DSP core and the codec hardware in a proper
  321 + * sequence.
  322 + */
  323 + ret = max98095_i2c_write(M98095_00F_HOST_CFG, 0);
  324 + if (ret != 0) {
  325 + debug("%s: Failed to reset DSP: %d\n", __func__, ret);
  326 + return ret;
  327 + }
  328 +
  329 + ret = max98095_i2c_write(M98095_097_PWR_SYS, 0);
  330 + if (ret != 0) {
  331 + debug("%s: Failed to reset codec: %d\n", __func__, ret);
  332 + return ret;
  333 + }
  334 +
  335 + /*
  336 + * Reset to hardware default for registers, as there is not a soft
  337 + * reset hardware control register.
  338 + */
  339 + for (i = M98095_010_HOST_INT_CFG; i < M98095_REG_MAX_CACHED; i++) {
  340 + ret = max98095_i2c_write(i, 0);
  341 + if (ret < 0) {
  342 + debug("%s: Failed to reset: %d\n", __func__, ret);
  343 + return ret;
  344 + }
  345 + }
  346 +
  347 + return 0;
  348 +}
  349 +
  350 +/*
  351 + * Intialise max98095 codec device
  352 + *
  353 + * @param max98095 max98095 information
  354 + *
  355 + * @returns -1 for error and 0 Success.
  356 + */
  357 +static int max98095_device_init(struct max98095_priv *max98095)
  358 +{
  359 + unsigned char id;
  360 + int error = 0;
  361 +
  362 + /* reset the codec, the DSP core, and disable all interrupts */
  363 + error = max98095_reset();
  364 + if (error != 0) {
  365 + debug("Reset\n");
  366 + return error;
  367 + }
  368 +
  369 + /* initialize private data */
  370 + max98095->sysclk = -1U;
  371 + max98095->rate = -1U;
  372 + max98095->fmt = -1U;
  373 +
  374 + error = max98095_i2c_read(M98095_0FF_REV_ID, &id);
  375 + if (error < 0) {
  376 + debug("%s: Failure reading hardware revision: %d\n",
  377 + __func__, id);
  378 + goto err_access;
  379 + }
  380 + debug("%s: Hardware revision: %c\n", __func__, (id - 0x40) + 'A');
  381 +
  382 + error |= max98095_i2c_write(M98095_097_PWR_SYS, M98095_PWRSV);
  383 +
  384 + /*
  385 + * initialize registers to hardware default configuring audio
  386 + * interface2 to DAC
  387 + */
  388 + error |= max98095_i2c_write(M98095_048_MIX_DAC_LR,
  389 + M98095_DAI2M_TO_DACL|M98095_DAI2M_TO_DACR);
  390 +
  391 + error |= max98095_i2c_write(M98095_092_PWR_EN_OUT,
  392 + M98095_SPK_SPREADSPECTRUM);
  393 + error |= max98095_i2c_write(M98095_045_CFG_DSP, M98095_DSPNORMAL);
  394 + error |= max98095_i2c_write(M98095_04E_CFG_HP, M98095_HPNORMAL);
  395 +
  396 + error |= max98095_i2c_write(M98095_02C_DAI1_IOCFG,
  397 + M98095_S1NORMAL|M98095_SDATA);
  398 +
  399 + error |= max98095_i2c_write(M98095_036_DAI2_IOCFG,
  400 + M98095_S2NORMAL|M98095_SDATA);
  401 +
  402 + error |= max98095_i2c_write(M98095_040_DAI3_IOCFG,
  403 + M98095_S3NORMAL|M98095_SDATA);
  404 +
  405 + /* take the codec out of the shut down */
  406 + error |= max98095_update_bits(M98095_097_PWR_SYS, M98095_SHDNRUN,
  407 + M98095_SHDNRUN);
  408 + /* route DACL and DACR output to HO and Spekers */
  409 + error |= max98095_i2c_write(M98095_050_MIX_SPK_LEFT, 0x01); /* DACL */
  410 + error |= max98095_i2c_write(M98095_051_MIX_SPK_RIGHT, 0x01);/* DACR */
  411 + error |= max98095_i2c_write(M98095_04C_MIX_HP_LEFT, 0x01); /* DACL */
  412 + error |= max98095_i2c_write(M98095_04D_MIX_HP_RIGHT, 0x01); /* DACR */
  413 +
  414 + /* power Enable */
  415 + error |= max98095_i2c_write(M98095_091_PWR_EN_OUT, 0xF3);
  416 +
  417 + /* set Volume */
  418 + error |= max98095_i2c_write(M98095_064_LVL_HP_L, 15);
  419 + error |= max98095_i2c_write(M98095_065_LVL_HP_R, 15);
  420 + error |= max98095_i2c_write(M98095_067_LVL_SPK_L, 16);
  421 + error |= max98095_i2c_write(M98095_068_LVL_SPK_R, 16);
  422 +
  423 + /* Enable DAIs */
  424 + error |= max98095_i2c_write(M98095_093_BIAS_CTRL, 0x30);
  425 + error |= max98095_i2c_write(M98095_096_PWR_DAC_CK, 0x07);
  426 +
  427 +err_access:
  428 + if (error < 0)
  429 + return -1;
  430 +
  431 + return 0;
  432 +}
  433 +
  434 +static int max98095_do_init(struct sound_codec_info *pcodec_info,
  435 + int sampling_rate, int mclk_freq,
  436 + int bits_per_sample)
  437 +{
  438 + int ret = 0;
  439 +
  440 + /* Enable codec clock */
  441 + set_xclkout();
  442 +
  443 + /* shift the device address by 1 for 7 bit addressing */
  444 + g_max98095_i2c_dev_addr = pcodec_info->i2c_dev_addr >> 1;
  445 +
  446 + if (pcodec_info->codec_type == CODEC_MAX_98095)
  447 + g_max98095_info.devtype = MAX98095;
  448 + else {
  449 + debug("%s: Codec id [%d] not defined\n", __func__,
  450 + pcodec_info->codec_type);
  451 + return -1;
  452 + }
  453 +
  454 + ret = max98095_device_init(&g_max98095_info);
  455 + if (ret < 0) {
  456 + debug("%s: max98095 codec chip init failed\n", __func__);
  457 + return ret;
  458 + }
  459 +
  460 + ret = max98095_set_sysclk(&g_max98095_info, mclk_freq);
  461 + if (ret < 0) {
  462 + debug("%s: max98095 codec set sys clock failed\n", __func__);
  463 + return ret;
  464 + }
  465 +
  466 + ret = max98095_hw_params(&g_max98095_info, sampling_rate,
  467 + bits_per_sample);
  468 +
  469 + if (ret == 0) {
  470 + ret = max98095_set_fmt(&g_max98095_info,
  471 + SND_SOC_DAIFMT_I2S |
  472 + SND_SOC_DAIFMT_NB_NF |
  473 + SND_SOC_DAIFMT_CBS_CFS);
  474 + }
  475 +
  476 + return ret;
  477 +}
  478 +
  479 +static int get_max98095_codec_values(struct sound_codec_info *pcodec_info,
  480 + const void *blob)
  481 +{
  482 + int error = 0;
  483 +#ifdef CONFIG_OF_CONTROL
  484 + enum fdt_compat_id compat;
  485 + int node;
  486 + int parent;
  487 +
  488 + /* Get the node from FDT for codec */
  489 + node = fdtdec_next_compatible(blob, 0, COMPAT_MAXIM_98095_CODEC);
  490 + if (node <= 0) {
  491 + debug("EXYNOS_SOUND: No node for codec in device tree\n");
  492 + debug("node = %d\n", node);
  493 + return -1;
  494 + }
  495 +
  496 + parent = fdt_parent_offset(blob, node);
  497 + if (parent < 0) {
  498 + debug("%s: Cannot find node parent\n", __func__);
  499 + return -1;
  500 + }
  501 +
  502 + compat = fdtdec_lookup(blob, parent);
  503 + switch (compat) {
  504 + case COMPAT_SAMSUNG_S3C2440_I2C:
  505 + pcodec_info->i2c_bus = i2c_get_bus_num_fdt(parent);
  506 + error |= pcodec_info->i2c_bus;
  507 + debug("i2c bus = %d\n", pcodec_info->i2c_bus);
  508 + pcodec_info->i2c_dev_addr = fdtdec_get_int(blob, node,
  509 + "reg", 0);
  510 + error |= pcodec_info->i2c_dev_addr;
  511 + debug("i2c dev addr = %x\n", pcodec_info->i2c_dev_addr);
  512 + break;
  513 + default:
  514 + debug("%s: Unknown compat id %d\n", __func__, compat);
  515 + return -1;
  516 + }
  517 +#else
  518 + pcodec_info->i2c_bus = AUDIO_I2C_BUS;
  519 + pcodec_info->i2c_dev_addr = AUDIO_I2C_REG;
  520 + debug("i2c dev addr = %d\n", pcodec_info->i2c_dev_addr);
  521 +#endif
  522 + pcodec_info->codec_type = CODEC_MAX_98095;
  523 + if (error == -1) {
  524 + debug("fail to get max98095 codec node properties\n");
  525 + return -1;
  526 + }
  527 +
  528 + return 0;
  529 +}
  530 +
  531 +/* max98095 Device Initialisation */
  532 +int max98095_init(const void *blob, int sampling_rate, int mclk_freq,
  533 + int bits_per_sample)
  534 +{
  535 + int ret;
  536 + int old_bus = i2c_get_bus_num();
  537 + struct sound_codec_info *pcodec_info = &g_codec_info;
  538 +
  539 + if (get_max98095_codec_values(pcodec_info, blob) < 0) {
  540 + debug("FDT Codec values failed\n");
  541 + return -1;
  542 + }
  543 +
  544 + i2c_set_bus_num(pcodec_info->i2c_bus);
  545 + ret = max98095_do_init(pcodec_info, sampling_rate, mclk_freq,
  546 + bits_per_sample);
  547 + i2c_set_bus_num(old_bus);
  548 +
  549 + return ret;
  550 +}
drivers/sound/max98095.h
  1 +/*
  2 + * max98095.h -- MAX98095 ALSA SoC Audio driver
  3 + *
  4 + * Copyright 2011 Maxim Integrated Products
  5 + *
  6 + * This program is free software; you can redistribute it and/or modify
  7 + * it under the terms of the GNU General Public License version 2 as
  8 + * published by the Free Software Foundation.
  9 + */
  10 +
  11 +#ifndef _MAX98095_H
  12 +#define _MAX98095_H
  13 +
  14 +/*
  15 + * MAX98095 Registers Definition
  16 + */
  17 +
  18 +#define M98095_000_HOST_DATA 0x00
  19 +#define M98095_001_HOST_INT_STS 0x01
  20 +#define M98095_002_HOST_RSP_STS 0x02
  21 +#define M98095_003_HOST_CMD_STS 0x03
  22 +#define M98095_004_CODEC_STS 0x04
  23 +#define M98095_005_DAI1_ALC_STS 0x05
  24 +#define M98095_006_DAI2_ALC_STS 0x06
  25 +#define M98095_007_JACK_AUTO_STS 0x07
  26 +#define M98095_008_JACK_MANUAL_STS 0x08
  27 +#define M98095_009_JACK_VBAT_STS 0x09
  28 +#define M98095_00A_ACC_ADC_STS 0x0A
  29 +#define M98095_00B_MIC_NG_AGC_STS 0x0B
  30 +#define M98095_00C_SPK_L_VOLT_STS 0x0C
  31 +#define M98095_00D_SPK_R_VOLT_STS 0x0D
  32 +#define M98095_00E_TEMP_SENSOR_STS 0x0E
  33 +#define M98095_00F_HOST_CFG 0x0F
  34 +#define M98095_010_HOST_INT_CFG 0x10
  35 +#define M98095_011_HOST_INT_EN 0x11
  36 +#define M98095_012_CODEC_INT_EN 0x12
  37 +#define M98095_013_JACK_INT_EN 0x13
  38 +#define M98095_014_JACK_INT_EN 0x14
  39 +#define M98095_015_DEC 0x15
  40 +#define M98095_016_RESERVED 0x16
  41 +#define M98095_017_RESERVED 0x17
  42 +#define M98095_018_KEYCODE3 0x18
  43 +#define M98095_019_KEYCODE2 0x19
  44 +#define M98095_01A_KEYCODE1 0x1A
  45 +#define M98095_01B_KEYCODE0 0x1B
  46 +#define M98095_01C_OEMCODE1 0x1C
  47 +#define M98095_01D_OEMCODE0 0x1D
  48 +#define M98095_01E_XCFG1 0x1E
  49 +#define M98095_01F_XCFG2 0x1F
  50 +#define M98095_020_XCFG3 0x20
  51 +#define M98095_021_XCFG4 0x21
  52 +#define M98095_022_XCFG5 0x22
  53 +#define M98095_023_XCFG6 0x23
  54 +#define M98095_024_XGPIO 0x24
  55 +#define M98095_025_XCLKCFG 0x25
  56 +#define M98095_026_SYS_CLK 0x26
  57 +#define M98095_027_DAI1_CLKMODE 0x27
  58 +#define M98095_028_DAI1_CLKCFG_HI 0x28
  59 +#define M98095_029_DAI1_CLKCFG_LO 0x29
  60 +#define M98095_02A_DAI1_FORMAT 0x2A
  61 +#define M98095_02B_DAI1_CLOCK 0x2B
  62 +#define M98095_02C_DAI1_IOCFG 0x2C
  63 +#define M98095_02D_DAI1_TDM 0x2D
  64 +#define M98095_02E_DAI1_FILTERS 0x2E
  65 +#define M98095_02F_DAI1_LVL1 0x2F
  66 +#define M98095_030_DAI1_LVL2 0x30
  67 +#define M98095_031_DAI2_CLKMODE 0x31
  68 +#define M98095_032_DAI2_CLKCFG_HI 0x32
  69 +#define M98095_033_DAI2_CLKCFG_LO 0x33
  70 +#define M98095_034_DAI2_FORMAT 0x34
  71 +#define M98095_035_DAI2_CLOCK 0x35
  72 +#define M98095_036_DAI2_IOCFG 0x36
  73 +#define M98095_037_DAI2_TDM 0x37
  74 +#define M98095_038_DAI2_FILTERS 0x38
  75 +#define M98095_039_DAI2_LVL1 0x39
  76 +#define M98095_03A_DAI2_LVL2 0x3A
  77 +#define M98095_03B_DAI3_CLKMODE 0x3B
  78 +#define M98095_03C_DAI3_CLKCFG_HI 0x3C
  79 +#define M98095_03D_DAI3_CLKCFG_LO 0x3D
  80 +#define M98095_03E_DAI3_FORMAT 0x3E
  81 +#define M98095_03F_DAI3_CLOCK 0x3F
  82 +#define M98095_040_DAI3_IOCFG 0x40
  83 +#define M98095_041_DAI3_TDM 0x41
  84 +#define M98095_042_DAI3_FILTERS 0x42
  85 +#define M98095_043_DAI3_LVL1 0x43
  86 +#define M98095_044_DAI3_LVL2 0x44
  87 +#define M98095_045_CFG_DSP 0x45
  88 +#define M98095_046_DAC_CTRL1 0x46
  89 +#define M98095_047_DAC_CTRL2 0x47
  90 +#define M98095_048_MIX_DAC_LR 0x48
  91 +#define M98095_049_MIX_DAC_M 0x49
  92 +#define M98095_04A_MIX_ADC_LEFT 0x4A
  93 +#define M98095_04B_MIX_ADC_RIGHT 0x4B
  94 +#define M98095_04C_MIX_HP_LEFT 0x4C
  95 +#define M98095_04D_MIX_HP_RIGHT 0x4D
  96 +#define M98095_04E_CFG_HP 0x4E
  97 +#define M98095_04F_MIX_RCV 0x4F
  98 +#define M98095_050_MIX_SPK_LEFT 0x50
  99 +#define M98095_051_MIX_SPK_RIGHT 0x51
  100 +#define M98095_052_MIX_SPK_CFG 0x52
  101 +#define M98095_053_MIX_LINEOUT1 0x53
  102 +#define M98095_054_MIX_LINEOUT2 0x54
  103 +#define M98095_055_MIX_LINEOUT_CFG 0x55
  104 +#define M98095_056_LVL_SIDETONE_DAI12 0x56
  105 +#define M98095_057_LVL_SIDETONE_DAI3 0x57
  106 +#define M98095_058_LVL_DAI1_PLAY 0x58
  107 +#define M98095_059_LVL_DAI1_EQ 0x59
  108 +#define M98095_05A_LVL_DAI2_PLAY 0x5A
  109 +#define M98095_05B_LVL_DAI2_EQ 0x5B
  110 +#define M98095_05C_LVL_DAI3_PLAY 0x5C
  111 +#define M98095_05D_LVL_ADC_L 0x5D
  112 +#define M98095_05E_LVL_ADC_R 0x5E
  113 +#define M98095_05F_LVL_MIC1 0x5F
  114 +#define M98095_060_LVL_MIC2 0x60
  115 +#define M98095_061_LVL_LINEIN 0x61
  116 +#define M98095_062_LVL_LINEOUT1 0x62
  117 +#define M98095_063_LVL_LINEOUT2 0x63
  118 +#define M98095_064_LVL_HP_L 0x64
  119 +#define M98095_065_LVL_HP_R 0x65
  120 +#define M98095_066_LVL_RCV 0x66
  121 +#define M98095_067_LVL_SPK_L 0x67
  122 +#define M98095_068_LVL_SPK_R 0x68
  123 +#define M98095_069_MICAGC_CFG 0x69
  124 +#define M98095_06A_MICAGC_THRESH 0x6A
  125 +#define M98095_06B_SPK_NOISEGATE 0x6B
  126 +#define M98095_06C_DAI1_ALC1_TIME 0x6C
  127 +#define M98095_06D_DAI1_ALC1_COMP 0x6D
  128 +#define M98095_06E_DAI1_ALC1_EXPN 0x6E
  129 +#define M98095_06F_DAI1_ALC1_GAIN 0x6F
  130 +#define M98095_070_DAI1_ALC2_TIME 0x70
  131 +#define M98095_071_DAI1_ALC2_COMP 0x71
  132 +#define M98095_072_DAI1_ALC2_EXPN 0x72
  133 +#define M98095_073_DAI1_ALC2_GAIN 0x73
  134 +#define M98095_074_DAI1_ALC3_TIME 0x74
  135 +#define M98095_075_DAI1_ALC3_COMP 0x75
  136 +#define M98095_076_DAI1_ALC3_EXPN 0x76
  137 +#define M98095_077_DAI1_ALC3_GAIN 0x77
  138 +#define M98095_078_DAI2_ALC1_TIME 0x78
  139 +#define M98095_079_DAI2_ALC1_COMP 0x79
  140 +#define M98095_07A_DAI2_ALC1_EXPN 0x7A
  141 +#define M98095_07B_DAI2_ALC1_GAIN 0x7B
  142 +#define M98095_07C_DAI2_ALC2_TIME 0x7C
  143 +#define M98095_07D_DAI2_ALC2_COMP 0x7D
  144 +#define M98095_07E_DAI2_ALC2_EXPN 0x7E
  145 +#define M98095_07F_DAI2_ALC2_GAIN 0x7F
  146 +#define M98095_080_DAI2_ALC3_TIME 0x80
  147 +#define M98095_081_DAI2_ALC3_COMP 0x81
  148 +#define M98095_082_DAI2_ALC3_EXPN 0x82
  149 +#define M98095_083_DAI2_ALC3_GAIN 0x83
  150 +#define M98095_084_HP_NOISE_GATE 0x84
  151 +#define M98095_085_AUX_ADC 0x85
  152 +#define M98095_086_CFG_LINE 0x86
  153 +#define M98095_087_CFG_MIC 0x87
  154 +#define M98095_088_CFG_LEVEL 0x88
  155 +#define M98095_089_JACK_DET_AUTO 0x89
  156 +#define M98095_08A_JACK_DET_MANUAL 0x8A
  157 +#define M98095_08B_JACK_KEYSCAN_DBC 0x8B
  158 +#define M98095_08C_JACK_KEYSCAN_DLY 0x8C
  159 +#define M98095_08D_JACK_KEY_THRESH 0x8D
  160 +#define M98095_08E_JACK_DC_SLEW 0x8E
  161 +#define M98095_08F_JACK_TEST_CFG 0x8F
  162 +#define M98095_090_PWR_EN_IN 0x90
  163 +#define M98095_091_PWR_EN_OUT 0x91
  164 +#define M98095_092_PWR_EN_OUT 0x92
  165 +#define M98095_093_BIAS_CTRL 0x93
  166 +#define M98095_094_PWR_DAC_21 0x94
  167 +#define M98095_095_PWR_DAC_03 0x95
  168 +#define M98095_096_PWR_DAC_CK 0x96
  169 +#define M98095_097_PWR_SYS 0x97
  170 +
  171 +#define M98095_0FF_REV_ID 0xFF
  172 +
  173 +#define M98095_REG_CNT (0xFF+1)
  174 +#define M98095_REG_MAX_CACHED 0X97
  175 +
  176 +/* MAX98095 Registers Bit Fields */
  177 +
  178 +/* M98095_00F_HOST_CFG */
  179 +#define M98095_SEG (1<<0)
  180 +#define M98095_XTEN (1<<1)
  181 +#define M98095_MDLLEN (1<<2)
  182 +
  183 +/* M98095_027_DAI1_CLKMODE, M98095_031_DAI2_CLKMODE, M98095_03B_DAI3_CLKMODE */
  184 +#define M98095_CLKMODE_MASK 0xFF
  185 +
  186 +/* M98095_02A_DAI1_FORMAT, M98095_034_DAI2_FORMAT, M98095_03E_DAI3_FORMAT */
  187 +#define M98095_DAI_MAS (1<<7)
  188 +#define M98095_DAI_WCI (1<<6)
  189 +#define M98095_DAI_BCI (1<<5)
  190 +#define M98095_DAI_DLY (1<<4)
  191 +#define M98095_DAI_TDM (1<<2)
  192 +#define M98095_DAI_FSW (1<<1)
  193 +#define M98095_DAI_WS (1<<0)
  194 +
  195 +/* M98095_02B_DAI1_CLOCK, M98095_035_DAI2_CLOCK, M98095_03F_DAI3_CLOCK */
  196 +#define M98095_DAI_BSEL64 (1<<0)
  197 +#define M98095_DAI_DOSR_DIV2 (0<<5)
  198 +#define M98095_DAI_DOSR_DIV4 (1<<5)
  199 +
  200 +/* M98095_02C_DAI1_IOCFG, M98095_036_DAI2_IOCFG, M98095_040_DAI3_IOCFG */
  201 +#define M98095_S1NORMAL (1<<6)
  202 +#define M98095_S2NORMAL (2<<6)
  203 +#define M98095_S3NORMAL (3<<6)
  204 +#define M98095_SDATA (3<<0)
  205 +
  206 +/* M98095_02E_DAI1_FILTERS, M98095_038_DAI2_FILTERS, M98095_042_DAI3_FILTERS */
  207 +#define M98095_DAI_DHF (1<<3)
  208 +
  209 +/* M98095_045_DSP_CFG */
  210 +#define M98095_DSPNORMAL (5<<4)
  211 +
  212 +/* M98095_048_MIX_DAC_LR */
  213 +#define M98095_DAI1L_TO_DACR (1<<7)
  214 +#define M98095_DAI1R_TO_DACR (1<<6)
  215 +#define M98095_DAI2M_TO_DACR (1<<5)
  216 +#define M98095_DAI1L_TO_DACL (1<<3)
  217 +#define M98095_DAI1R_TO_DACL (1<<2)
  218 +#define M98095_DAI2M_TO_DACL (1<<1)
  219 +#define M98095_DAI3M_TO_DACL (1<<0)
  220 +
  221 +/* M98095_049_MIX_DAC_M */
  222 +#define M98095_DAI1L_TO_DACM (1<<3)
  223 +#define M98095_DAI1R_TO_DACM (1<<2)
  224 +#define M98095_DAI2M_TO_DACM (1<<1)
  225 +#define M98095_DAI3M_TO_DACM (1<<0)
  226 +
  227 +/* M98095_04E_MIX_HP_CFG */
  228 +#define M98095_HPNORMAL (3<<4)
  229 +
  230 +/* M98095_05F_LVL_MIC1, M98095_060_LVL_MIC2 */
  231 +#define M98095_MICPRE_MASK (3<<5)
  232 +#define M98095_MICPRE_SHIFT 5
  233 +
  234 +/* M98095_064_LVL_HP_L, M98095_065_LVL_HP_R */
  235 +#define M98095_HP_MUTE (1<<7)
  236 +
  237 +/* M98095_066_LVL_RCV */
  238 +#define M98095_REC_MUTE (1<<7)
  239 +
  240 +/* M98095_067_LVL_SPK_L, M98095_068_LVL_SPK_R */
  241 +#define M98095_SP_MUTE (1<<7)
  242 +
  243 +/* M98095_087_CFG_MIC */
  244 +#define M98095_MICSEL_MASK (3<<0)
  245 +#define M98095_DIGMIC_L (1<<2)
  246 +#define M98095_DIGMIC_R (1<<3)
  247 +#define M98095_DIGMIC2L (1<<4)
  248 +#define M98095_DIGMIC2R (1<<5)
  249 +
  250 +/* M98095_088_CFG_LEVEL */
  251 +#define M98095_VSEN (1<<6)
  252 +#define M98095_ZDEN (1<<5)
  253 +#define M98095_BQ2EN (1<<3)
  254 +#define M98095_BQ1EN (1<<2)
  255 +#define M98095_EQ2EN (1<<1)
  256 +#define M98095_EQ1EN (1<<0)
  257 +
  258 +/* M98095_090_PWR_EN_IN */
  259 +#define M98095_INEN (1<<7)
  260 +#define M98095_MB2EN (1<<3)
  261 +#define M98095_MB1EN (1<<2)
  262 +#define M98095_MBEN (3<<2)
  263 +#define M98095_ADREN (1<<1)
  264 +#define M98095_ADLEN (1<<0)
  265 +
  266 +/* M98095_091_PWR_EN_OUT */
  267 +#define M98095_HPLEN (1<<7)
  268 +#define M98095_HPREN (1<<6)
  269 +#define M98095_SPLEN (1<<5)
  270 +#define M98095_SPREN (1<<4)
  271 +#define M98095_RECEN (1<<3)
  272 +#define M98095_DALEN (1<<1)
  273 +#define M98095_DAREN (1<<0)
  274 +
  275 +/* M98095_092_PWR_EN_OUT */
  276 +#define M98095_SPK_FIXEDSPECTRUM (0<<4)
  277 +#define M98095_SPK_SPREADSPECTRUM (1<<4)
  278 +
  279 +/* M98095_097_PWR_SYS */
  280 +#define M98095_SHDNRUN (1<<7)
  281 +#define M98095_PERFMODE (1<<3)
  282 +#define M98095_HPPLYBACK (1<<2)
  283 +#define M98095_PWRSV8K (1<<1)
  284 +#define M98095_PWRSV (1<<0)
  285 +
  286 +#define M98095_COEFS_PER_BAND 5
  287 +
  288 +/* Equalizer filter coefficients */
  289 +#define M98095_110_DAI1_EQ_BASE 0x10
  290 +#define M98095_142_DAI2_EQ_BASE 0x42
  291 +
  292 +/* Biquad filter coefficients */
  293 +#define M98095_174_DAI1_BQ_BASE 0x74
  294 +#define M98095_17E_DAI2_BQ_BASE 0x7E
  295 +
  296 +/* function prototype */
  297 +
  298 +/*
  299 + * intialise max98095 sound codec device for the given configuration
  300 + *
  301 + * @param blob FDT node for codec values
  302 + * @param sampling_rate Sampling rate (Hz)
  303 + * @param mclk_freq MCLK Frequency (Hz)
  304 + * @param bits_per_sample bits per Sample (must be 16 or 24)
  305 + *
  306 + * @returns -1 for error and 0 Success.
  307 + */
  308 +int max98095_init(const void *blob, int sampling_rate, int mclk_freq,
  309 + int bits_per_sample);
  310 +
  311 +#endif
drivers/sound/sound.c
... ... @@ -31,6 +31,7 @@
31 31 #include <sound.h>
32 32 #include <asm/arch/sound.h>
33 33 #include "wm8994.h"
  34 +#include "max98095.h"
34 35  
35 36 /* defines */
36 37 #define SOUND_400_HZ 400
37 38  
38 39  
... ... @@ -149,11 +150,15 @@
149 150 pi2s_tx->samplingrate,
150 151 (pi2s_tx->samplingrate * (pi2s_tx->rfs)),
151 152 pi2s_tx->bitspersample, pi2s_tx->channels);
  153 + } else if (!strcmp(codectype, "max98095")) {
  154 + ret = max98095_init(blob, pi2s_tx->samplingrate,
  155 + (pi2s_tx->samplingrate * (pi2s_tx->rfs)),
  156 + pi2s_tx->bitspersample);
152 157 } else {
153   - debug("%s: Unknown code type %s\n", __func__,
154   - codectype);
  158 + debug("%s: Unknown codec type %s\n", __func__, codectype);
155 159 return -1;
156 160 }
  161 +
157 162 if (ret) {
158 163 debug("%s: Codec init failed\n", __func__);
159 164 return -1;
include/configs/exynos5250-dt.h
... ... @@ -118,6 +118,11 @@
118 118 #define CONFIG_BOOTDELAY 3
119 119 #define CONFIG_ZERO_BOOTDELAY_CHECK
120 120  
  121 +/* Thermal Management Unit */
  122 +#define CONFIG_EXYNOS_TMU
  123 +#define CONFIG_CMD_DTT
  124 +#define CONFIG_TMU_CMD_DTT
  125 +
121 126 /* USB */
122 127 #define CONFIG_CMD_USB
123 128 #define CONFIG_USB_EHCI
... ... @@ -297,6 +302,7 @@
297 302 #ifdef CONFIG_CMD_SOUND
298 303 #define CONFIG_SOUND
299 304 #define CONFIG_I2S
  305 +#define CONFIG_SOUND_MAX98095
300 306 #define CONFIG_SOUND_WM8994
301 307 #endif
302 308  
include/configs/snow.h
  1 +/*
  2 + * Copyright (C) 2013 Samsung Electronics
  3 + *
  4 + * Configuration settings for the SAMSUNG EXYNOS5 Snow board.
  5 + *
  6 + * See file CREDITS for list of people who contributed to this
  7 + * project.
  8 + *
  9 + * This program is free software; you can redistribute it and/or
  10 + * modify it under the terms of the GNU General Public License as
  11 + * published by the Free Software Foundation; either version 2 of
  12 + * the License, or (at your option) any later version.
  13 + *
  14 + * This program is distributed in the hope that it will be useful,
  15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17 + * GNU General Public License for more details.
  18 + *
  19 + * You should have received a copy of the GNU General Public License
  20 + * along with this program; if not, write to the Free Software
  21 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  22 + * MA 02111-1307 USA
  23 + */
  24 +
  25 +#ifndef __CONFIG_SNOW_H
  26 +#define __CONFIG_SNOW_H
  27 +
  28 +#include <configs/exynos5250-dt.h>
  29 +
  30 +#undef CONFIG_DEFAULT_DEVICE_TREE
  31 +#define CONFIG_DEFAULT_DEVICE_TREE exynos5250-snow
  32 +
  33 +#endif /* __CONFIG_SNOW_H */
... ... @@ -83,7 +83,9 @@
83 83 COMPAT_SAMSUNG_EXYNOS_SPI, /* Exynos SPI */
84 84 COMPAT_SAMSUNG_EXYNOS_EHCI, /* Exynos EHCI controller */
85 85 COMPAT_SAMSUNG_EXYNOS_USB_PHY, /* Exynos phy controller for usb2.0 */
  86 + COMPAT_SAMSUNG_EXYNOS_TMU, /* Exynos TMU */
86 87 COMPAT_MAXIM_MAX77686_PMIC, /* MAX77686 PMIC */
  88 + COMPAT_MAXIM_98095_CODEC, /* MAX98095 Codec */
87 89  
88 90 COMPAT_COUNT,
89 91 };
include/power/max77686_pmic.h
... ... @@ -155,5 +155,37 @@
155 155 EN_LDO = (0x3 << 6),
156 156 };
157 157  
  158 +/* Buck1 1 volt value */
  159 +#define MAX77686_BUCK1OUT_1V 0x5
  160 +#define MAX77686_BUCK1CTRL_EN (3 << 0)
  161 +/* Buck2 1.3 volt value */
  162 +#define MAX77686_BUCK2DVS1_1_3V 0x38
  163 +#define MAX77686_BUCK2CTRL_ON (1 << 4)
  164 +/* Buck3 1.0125 volt value */
  165 +#define MAX77686_BUCK3DVS1_1_0125V 0x21
  166 +#define MAX77686_BUCK3CTRL_ON (1 << 4)
  167 +/* Buck4 1.2 volt value */
  168 +#define MAX77686_BUCK4DVS1_1_2V 0x30
  169 +#define MAX77686_BUCK4CTRL_ON (1 << 4)
  170 +/* LDO2 1.5 volt value */
  171 +#define MAX77686_LD02CTRL1_1_5V 0x1c
  172 +/* LDO3 1.8 volt value */
  173 +#define MAX77686_LD03CTRL1_1_8V 0x14
  174 +/* LDO5 1.8 volt value */
  175 +#define MAX77686_LD05CTRL1_1_8V 0x14
  176 +/* LDO10 1.8 volt value */
  177 +#define MAX77686_LD10CTRL1_1_8V 0x14
  178 +/*
  179 + * MAX77686_REG_PMIC_32KHZ set to 32KH CP
  180 + * output is activated
  181 + */
  182 +#define MAX77686_32KHCP_EN (1 << 1)
  183 +/*
  184 + * MAX77686_REG_PMIC_BBAT set to
  185 + * Back up batery charger on and
  186 + * limit voltage setting to 3.5v
  187 + */
  188 +#define MAX77686_BBCHOSTEN (1 << 0)
  189 +#define MAX77686_BBCVS_3_5V (3 << 3)
158 190 #endif /* __MAX77686_PMIC_H_ */
... ... @@ -28,6 +28,7 @@
28 28 enum en_sound_codec {
29 29 CODEC_WM_8994,
30 30 CODEC_WM_8995,
  31 + CODEC_MAX_98095,
31 32 CODEC_MAX
32 33 };
33 34  
  1 +/*
  2 + * Copyright (c) 2012 Samsung Electronics Co., Ltd.
  3 + * http://www.samsung.com
  4 + * Akshay Saraswat <akshay.s@samsung.com>
  5 + *
  6 + * Thermal Management Unit
  7 + *
  8 + * See file CREDITS for list of people who contributed to this
  9 + * project.
  10 + *
  11 + * This program is free software; you can redistribute it and/or modify
  12 + * it under the terms of the GNU General Public License version 2 as
  13 + * published by the Free Software Foundation.
  14 + * You should have received a copy of the GNU General Public License
  15 + * along with this program; if not, write to the Free Software
  16 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  17 + * MA 02111-1307 USA
  18 + */
  19 +
  20 +#ifndef _TMU_H
  21 +#define _TMU_H
  22 +
  23 +enum tmu_status_t {
  24 + TMU_STATUS_INIT = -1,
  25 + TMU_STATUS_NORMAL = 0,
  26 + TMU_STATUS_WARNING,
  27 + TMU_STATUS_TRIPPED,
  28 +};
  29 +
  30 +/*
  31 + * Monitors status of the TMU device and exynos temperature
  32 + *
  33 + * @param temp pointer to the current temperature value
  34 + * @return enum tmu_status_t value, code indicating event to execute
  35 + * and -1 on error
  36 + */
  37 +enum tmu_status_t tmu_monitor(int *temp);
  38 +
  39 +/*
  40 + * Initialize TMU device
  41 + *
  42 + * @param blob FDT blob
  43 + * @return int value, 0 for success
  44 + */
  45 +int tmu_init(const void *blob);
  46 +#endif /* _THERMAL_H_ */
... ... @@ -58,7 +58,9 @@
58 58 COMPAT(SAMSUNG_EXYNOS_SPI, "samsung,exynos-spi"),
59 59 COMPAT(SAMSUNG_EXYNOS_EHCI, "samsung,exynos-ehci"),
60 60 COMPAT(SAMSUNG_EXYNOS_USB_PHY, "samsung,exynos-usb-phy"),
  61 + COMPAT(SAMSUNG_EXYNOS_TMU, "samsung,exynos-tmu"),
61 62 COMPAT(MAXIM_MAX77686_PMIC, "maxim,max77686_pmic"),
  63 + COMPAT(MAXIM_98095_CODEC, "maxim,max98095-codec"),
62 64 };
63 65  
64 66 const char *fdtdec_get_compatible(enum fdt_compat_id id)