Gale: Add LED support.
[depthcharge.git] / src / drivers / bus / i2c / ipq40xx_blsp.c
1 /*
2  * This file is part of the depthcharge project.
3  *
4  * Copyright (C) 2014 - 2015 The Linux Foundation. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are
8  * met:
9  *     * Redistributions of source code must retain the above copyright
10  *       notice, this list of conditions and the following disclaimer.
11  *     * Redistributions in binary form must reproduce the above
12  *       copyright notice, this list of conditions and the following
13  *       disclaimer in the documentation and/or other materials provided
14  *       with the distribution.
15  *     * Neither the name of The Linux Foundation nor the names of its
16  *       contributors may be used to endorse or promote products derived
17  *       from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
20  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
26  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
28  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
29  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include <libpayload.h>
33 #include <arch/io.h>
34 #include "base/container_of.h"
35 #include "base/init_funcs.h"
36 #include "drivers/gpio/ipq40xx.h"
37 #include "drivers/bus/spi/ipq40xx.h"
38 #include "ipq40xx_blsp.h"
39
40 #define SCL_GPIO        20
41 #define SDA_GPIO        21
42 #define GPIO_FUNC_SCL   0x1
43 #define GPIO_FUNC_SDA   0x1
44
45 #define SCL_GPIO_I2C1       34
46 #define SDA_GPIO_I2C1       35
47 #define GPIO_I2C1_FUNC_SCL  0x1
48 #define GPIO_I2C1_FUNC_SDA  0x1
49
50 int blsp_init_board(blsp_qup_id_t id)
51 {
52         switch (id) {
53         case BLSP_QUP_ID_0:
54         case BLSP_QUP_ID_1:
55         case BLSP_QUP_ID_2:
56         case BLSP_QUP_ID_3:
57                 /* Configure GPIOs 20 - SCL, 21 - SDA, 2mA gpio_en */
58                 gpio_tlmm_config_set(SDA_GPIO, GPIO_FUNC_SDA,
59                         GPIO_NO_PULL, GPIO_2MA, 1);
60                 gpio_tlmm_config_set(SCL_GPIO, GPIO_FUNC_SCL,
61                         GPIO_NO_PULL, GPIO_2MA, 1);
62
63                 /* Configure GPIOs 34 - SCL, 35 - SDA, 2mA gpio_en */
64                 gpio_tlmm_config_set(SDA_GPIO_I2C1, GPIO_I2C1_FUNC_SDA,
65                         GPIO_NO_PULL, GPIO_2MA, 1);
66                 gpio_tlmm_config_set(SCL_GPIO_I2C1, GPIO_I2C1_FUNC_SCL,
67                         GPIO_NO_PULL, GPIO_2MA, 1);
68
69                 break;
70         default:
71                 return 1;
72         }
73
74         return 0;
75 }
76
77 int blsp_i2c_clock_config(blsp_qup_id_t id)
78 {
79 #if 0
80 Not sure if this is needed. Coreboot has done this
81
82         int i;
83         const int max_tries = 200;
84         struct { void *cbcr, *cmd, *cfg; } clk[] = {
85                 {
86                         GCC_BLSP1_QUP1_I2C_APPS_CBCR,
87                         GCC_BLSP1_QUP1_I2C_APPS_CMD_RCGR,
88                         GCC_BLSP1_QUP1_I2C_APPS_CFG_RCGR,
89                 },
90                 {
91                         GCC_BLSP1_QUP1_I2C_APPS_CBCR,
92                         GCC_BLSP1_QUP1_I2C_APPS_CMD_RCGR,
93                         GCC_BLSP1_QUP1_I2C_APPS_CFG_RCGR,
94                 },
95                 {
96                         GCC_BLSP1_QUP1_I2C_APPS_CBCR,
97                         GCC_BLSP1_QUP1_I2C_APPS_CMD_RCGR,
98                         GCC_BLSP1_QUP1_I2C_APPS_CFG_RCGR,
99                 },
100                 {
101                         GCC_BLSP1_QUP1_I2C_APPS_CBCR,
102                         GCC_BLSP1_QUP1_I2C_APPS_CMD_RCGR,
103                         GCC_BLSP1_QUP1_I2C_APPS_CFG_RCGR,
104                 },
105         };
106
107         /* uart_clock_config() does this, duplication should be ok... */
108         setbits_le32(GCC_CLK_BRANCH_ENA, BLSP1_AHB | BLSP1_SLEEP);
109
110         if (clk[id].cbcr == NULL)
111                 return -EINVAL;
112
113         /* Src Sel 1 (fepll 200), Src Div 10.5 */
114         write32(clk[id].cfg, (1u << 8) | (20u << 0));
115
116         write32(clk[id].cmd, BIT(0)); /* Update En */
117
118         for (i = 0; i < max_tries; i++) {
119                 if (read32(clk[id].cmd) & BIT(0)) {
120                         udelay(5);
121                         continue;
122                 }
123                 break;
124         }
125
126         if (i == max_tries) {
127                 printk(BIOS_ERR, "== %s failed ==\n", __func__);
128                 return -ETIMEDOUT;
129         }
130
131         write32(clk[id].cbcr, BIT(0));  /* Enable */
132 #endif
133
134         return 0;
135 }
136
137 blsp_return_t blsp_init(blsp_qup_id_t id, blsp_protocol_t protocol)
138 {
139         void *base = blsp_qup_base(id);
140
141         if (!base)
142                 return BLSP_ID_ERROR;
143
144         /* Configure Mini core to I2C core */
145         clrsetbits_le32(base, QUP_CONFIG_MINI_CORE_MSK,
146                                 QUP_CONFIG_MINI_CORE_I2C);
147
148         return BLSP_SUCCESS;
149 }