| .. | .. |
|---|
| 13 | 13 | #include <linux/gpio/consumer.h> |
|---|
| 14 | 14 | #include <linux/mfd/rk630.h> |
|---|
| 15 | 15 | |
|---|
| 16 | | -static int rk630_macphy_enable(struct rk630 *rk630) |
|---|
| 16 | +static int rk630_macphy_enable(struct rk630 *rk630, unsigned long rate) |
|---|
| 17 | 17 | { |
|---|
| 18 | 18 | u32 val; |
|---|
| 19 | 19 | int ret; |
|---|
| .. | .. |
|---|
| 68 | 68 | return ret; |
|---|
| 69 | 69 | } |
|---|
| 70 | 70 | |
|---|
| 71 | | - /* mode sel: RMII && clock sel: 24M && BGS value: OTP && id */ |
|---|
| 72 | | - val = (2 << 14) | (0 << 12) | (0x1 << 8) | (6 << 5) | 1; |
|---|
| 71 | + /* mode sel: RMII && BGS value: OTP && id */ |
|---|
| 72 | + val = (2 << 14) | (0 << 12) | (0x1 << 8) | 1; |
|---|
| 73 | + switch (rate) { |
|---|
| 74 | + case 24000000: |
|---|
| 75 | + val |= 0x6 << 5; |
|---|
| 76 | + break; |
|---|
| 77 | + case 25000000: |
|---|
| 78 | + val |= 0x4 << 5; |
|---|
| 79 | + break; |
|---|
| 80 | + case 27000000: |
|---|
| 81 | + val |= 0x5 << 5; |
|---|
| 82 | + break; |
|---|
| 83 | + default: |
|---|
| 84 | + dev_err(rk630->dev, "Unsupported clock rate: %ld\n", rate); |
|---|
| 85 | + return -EINVAL; |
|---|
| 86 | + } |
|---|
| 87 | + |
|---|
| 73 | 88 | ret = regmap_write(rk630->grf, GRF_REG(0x404), val | 0xffff0000); |
|---|
| 74 | 89 | if (ret != 0) { |
|---|
| 75 | 90 | dev_err(rk630->dev, "Could not write to GRF: %d\n", ret); |
|---|
| .. | .. |
|---|
| 100 | 115 | { |
|---|
| 101 | 116 | .name = "rk630-tve", |
|---|
| 102 | 117 | .of_compatible = "rockchip,rk630-tve", |
|---|
| 118 | + }, |
|---|
| 119 | + { |
|---|
| 120 | + .name = "rk630-rtc", |
|---|
| 121 | + .of_compatible = "rockchip,rk630-rtc", |
|---|
| 103 | 122 | }, |
|---|
| 104 | 123 | { |
|---|
| 105 | 124 | .name = "rk630-macphy", |
|---|
| .. | .. |
|---|
| 164 | 183 | }; |
|---|
| 165 | 184 | EXPORT_SYMBOL_GPL(rk630_cru_regmap_config); |
|---|
| 166 | 185 | |
|---|
| 186 | +static const struct regmap_range rk630_rtc_readable_ranges[] = { |
|---|
| 187 | + regmap_reg_range(RTC_SET_SECONDS, RTC_CNT_3), |
|---|
| 188 | +}; |
|---|
| 189 | + |
|---|
| 190 | +static const struct regmap_access_table rk630_rtc_readable_table = { |
|---|
| 191 | + .yes_ranges = rk630_rtc_readable_ranges, |
|---|
| 192 | + .n_yes_ranges = ARRAY_SIZE(rk630_rtc_readable_ranges), |
|---|
| 193 | +}; |
|---|
| 194 | + |
|---|
| 195 | +const struct regmap_config rk630_rtc_regmap_config = { |
|---|
| 196 | + .name = "rtc", |
|---|
| 197 | + .reg_bits = 32, |
|---|
| 198 | + .val_bits = 32, |
|---|
| 199 | + .reg_stride = 4, |
|---|
| 200 | + .max_register = RTC_MAX_REGISTER, |
|---|
| 201 | + .reg_format_endian = REGMAP_ENDIAN_NATIVE, |
|---|
| 202 | + .val_format_endian = REGMAP_ENDIAN_NATIVE, |
|---|
| 203 | + .rd_table = &rk630_rtc_readable_table, |
|---|
| 204 | +}; |
|---|
| 205 | +EXPORT_SYMBOL_GPL(rk630_rtc_regmap_config); |
|---|
| 206 | + |
|---|
| 167 | 207 | int rk630_core_probe(struct rk630 *rk630) |
|---|
| 168 | 208 | { |
|---|
| 169 | 209 | bool macphy_enabled = false; |
|---|
| 210 | + struct clk *ref_clk; |
|---|
| 170 | 211 | struct device_node *np; |
|---|
| 212 | + unsigned long rate; |
|---|
| 171 | 213 | int ret; |
|---|
| 214 | + |
|---|
| 215 | + if (!rk630->irq) { |
|---|
| 216 | + dev_err(rk630->dev, "No interrupt support, no core IRQ\n"); |
|---|
| 217 | + return -EINVAL; |
|---|
| 218 | + } |
|---|
| 219 | + |
|---|
| 220 | + ref_clk = devm_clk_get(rk630->dev, "ref"); |
|---|
| 221 | + if (IS_ERR(ref_clk)) { |
|---|
| 222 | + dev_err(rk630->dev, "failed to get ref clk source\n"); |
|---|
| 223 | + return PTR_ERR(ref_clk); |
|---|
| 224 | + } |
|---|
| 225 | + |
|---|
| 226 | + ret = clk_prepare_enable(ref_clk); |
|---|
| 227 | + if (ret < 0) { |
|---|
| 228 | + dev_err(rk630->dev, "failed to enable ref clk - %d\n", ret); |
|---|
| 229 | + return ret; |
|---|
| 230 | + } |
|---|
| 231 | + rate = clk_get_rate(ref_clk); |
|---|
| 232 | + |
|---|
| 233 | + ret = devm_add_action_or_reset(rk630->dev, (void (*) (void *))clk_disable_unprepare, |
|---|
| 234 | + ref_clk); |
|---|
| 235 | + if (ret) |
|---|
| 236 | + return ret; |
|---|
| 172 | 237 | |
|---|
| 173 | 238 | rk630->reset_gpio = devm_gpiod_get(rk630->dev, "reset", 0); |
|---|
| 174 | 239 | if (IS_ERR(rk630->reset_gpio)) { |
|---|
| .. | .. |
|---|
| 182 | 247 | gpiod_direction_output(rk630->reset_gpio, 1); |
|---|
| 183 | 248 | usleep_range(50000, 60000); |
|---|
| 184 | 249 | gpiod_direction_output(rk630->reset_gpio, 0); |
|---|
| 250 | + |
|---|
| 251 | + /** |
|---|
| 252 | + * If rtc output clamp is enabled, rtc regs can't be accessed, |
|---|
| 253 | + * RK630 irq add will failed. |
|---|
| 254 | + */ |
|---|
| 255 | + regmap_update_bits(rk630->grf, PLUMAGE_GRF_SOC_CON0, |
|---|
| 256 | + RTC_CLAMP_EN_MASK, RTC_CLAMP_EN(1)); |
|---|
| 257 | + |
|---|
| 258 | + /* disable ext_off\vbat_det\msec\sys_int\periodic interrupt by default */ |
|---|
| 259 | + regmap_write(rk630->rtc, RTC_INT1_EN, 0); |
|---|
| 185 | 260 | |
|---|
| 186 | 261 | ret = devm_mfd_add_devices(rk630->dev, PLATFORM_DEVID_NONE, |
|---|
| 187 | 262 | rk630_devs, ARRAY_SIZE(rk630_devs), |
|---|
| .. | .. |
|---|
| 204 | 279 | } |
|---|
| 205 | 280 | |
|---|
| 206 | 281 | if (macphy_enabled) |
|---|
| 207 | | - rk630_macphy_enable(rk630); |
|---|
| 282 | + rk630_macphy_enable(rk630, rate); |
|---|
| 208 | 283 | else |
|---|
| 209 | 284 | rk630_macphy_disable(rk630); |
|---|
| 210 | 285 | |
|---|