Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: phy: micrel: Add support for PTP_PF_EXTTS for lan8814

Extend the PTP programmable gpios to implement also PTP_PF_EXTTS
function. The pins can be configured to capture both of rising
and falling edge. Once the event is seen, then an interrupt is
generated and the LTC is saved in the registers.
On lan8814 only GPIO 3 can be configured for this.

This was tested using:
ts2phc -m -l 7 -s generic -f ts2phc.cfg

Where the configuration was the following:
---
[global]
ts2phc.pin_index 3

[eth0]
---

Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>
Signed-off-by: Horatiu Vultur <horatiu.vultur@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Horatiu Vultur and committed by
David S. Miller
b3f1a08f 3208bdd0

+181 -1
+181 -1
drivers/net/phy/micrel.c
··· 167 167 #define PTP_CMD_CTL_PTP_LTC_STEP_SEC_ BIT(5) 168 168 #define PTP_CMD_CTL_PTP_LTC_STEP_NSEC_ BIT(6) 169 169 170 + #define PTP_COMMON_INT_ENA 0x0204 171 + #define PTP_COMMON_INT_ENA_GPIO_CAP_EN BIT(2) 172 + 170 173 #define PTP_CLOCK_SET_SEC_HI 0x0205 171 174 #define PTP_CLOCK_SET_SEC_MID 0x0206 172 175 #define PTP_CLOCK_SET_SEC_LO 0x0207 ··· 181 178 #define PTP_CLOCK_READ_SEC_LO 0x022B 182 179 #define PTP_CLOCK_READ_NS_HI 0x022C 183 180 #define PTP_CLOCK_READ_NS_LO 0x022D 181 + 182 + #define PTP_GPIO_SEL 0x0230 183 + #define PTP_GPIO_SEL_GPIO_SEL(pin) ((pin) << 8) 184 + #define PTP_GPIO_CAP_MAP_LO 0x0232 185 + 186 + #define PTP_GPIO_CAP_EN 0x0233 187 + #define PTP_GPIO_CAP_EN_GPIO_RE_CAPTURE_ENABLE(gpio) BIT(gpio) 188 + #define PTP_GPIO_CAP_EN_GPIO_FE_CAPTURE_ENABLE(gpio) (BIT(gpio) << 8) 189 + 190 + #define PTP_GPIO_RE_LTC_SEC_HI_CAP 0x0235 191 + #define PTP_GPIO_RE_LTC_SEC_LO_CAP 0x0236 192 + #define PTP_GPIO_RE_LTC_NS_HI_CAP 0x0237 193 + #define PTP_GPIO_RE_LTC_NS_LO_CAP 0x0238 194 + #define PTP_GPIO_FE_LTC_SEC_HI_CAP 0x0239 195 + #define PTP_GPIO_FE_LTC_SEC_LO_CAP 0x023A 196 + #define PTP_GPIO_FE_LTC_NS_HI_CAP 0x023B 197 + #define PTP_GPIO_FE_LTC_NS_LO_CAP 0x023C 198 + 199 + #define PTP_GPIO_CAP_STS 0x023D 200 + #define PTP_GPIO_CAP_STS_PTP_GPIO_RE_STS(gpio) BIT(gpio) 201 + #define PTP_GPIO_CAP_STS_PTP_GPIO_FE_STS(gpio) (BIT(gpio) << 8) 184 202 185 203 #define PTP_OPERATING_MODE 0x0241 186 204 #define PTP_OPERATING_MODE_STANDALONE_ BIT(0) ··· 298 274 299 275 #define LAN8814_PTP_GPIO_NUM 24 300 276 #define LAN8814_PTP_PEROUT_NUM 2 277 + #define LAN8814_PTP_EXTTS_NUM 3 301 278 302 279 #define LAN8814_BUFFER_TIME 2 303 280 ··· 3149 3124 return 0; 3150 3125 } 3151 3126 3127 + static void lan8814_ptp_extts_on(struct phy_device *phydev, int pin, u32 flags) 3128 + { 3129 + u16 tmp; 3130 + 3131 + /* Set as gpio input */ 3132 + tmp = lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin)); 3133 + tmp &= ~LAN8814_GPIO_DIR_BIT(pin); 3134 + lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), tmp); 3135 + 3136 + /* Map the pin to ltc pin 0 of the capture map registers */ 3137 + tmp = lanphy_read_page_reg(phydev, 4, PTP_GPIO_CAP_MAP_LO); 3138 + tmp |= pin; 3139 + lanphy_write_page_reg(phydev, 4, PTP_GPIO_CAP_MAP_LO, tmp); 3140 + 3141 + /* Enable capture on the edges of the ltc pin */ 3142 + tmp = lanphy_read_page_reg(phydev, 4, PTP_GPIO_CAP_EN); 3143 + if (flags & PTP_RISING_EDGE) 3144 + tmp |= PTP_GPIO_CAP_EN_GPIO_RE_CAPTURE_ENABLE(0); 3145 + if (flags & PTP_FALLING_EDGE) 3146 + tmp |= PTP_GPIO_CAP_EN_GPIO_FE_CAPTURE_ENABLE(0); 3147 + lanphy_write_page_reg(phydev, 4, PTP_GPIO_CAP_EN, tmp); 3148 + 3149 + /* Enable interrupt top interrupt */ 3150 + tmp = lanphy_read_page_reg(phydev, 4, PTP_COMMON_INT_ENA); 3151 + tmp |= PTP_COMMON_INT_ENA_GPIO_CAP_EN; 3152 + lanphy_write_page_reg(phydev, 4, PTP_COMMON_INT_ENA, tmp); 3153 + } 3154 + 3155 + static void lan8814_ptp_extts_off(struct phy_device *phydev, int pin) 3156 + { 3157 + u16 tmp; 3158 + 3159 + /* Set as gpio out */ 3160 + tmp = lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin)); 3161 + tmp |= LAN8814_GPIO_DIR_BIT(pin); 3162 + lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_DIR_ADDR(pin), tmp); 3163 + 3164 + /* Enable alternate, 0:for alternate function, 1:gpio */ 3165 + tmp = lanphy_read_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin)); 3166 + tmp &= ~LAN8814_GPIO_EN_BIT(pin); 3167 + lanphy_write_page_reg(phydev, 4, LAN8814_GPIO_EN_ADDR(pin), tmp); 3168 + 3169 + /* Clear the mapping of pin to registers 0 of the capture registers */ 3170 + tmp = lanphy_read_page_reg(phydev, 4, PTP_GPIO_CAP_MAP_LO); 3171 + tmp &= ~GENMASK(3, 0); 3172 + lanphy_write_page_reg(phydev, 4, PTP_GPIO_CAP_MAP_LO, tmp); 3173 + 3174 + /* Disable capture on both of the edges */ 3175 + tmp = lanphy_read_page_reg(phydev, 4, PTP_GPIO_CAP_EN); 3176 + tmp &= ~PTP_GPIO_CAP_EN_GPIO_RE_CAPTURE_ENABLE(pin); 3177 + tmp &= ~PTP_GPIO_CAP_EN_GPIO_FE_CAPTURE_ENABLE(pin); 3178 + lanphy_write_page_reg(phydev, 4, PTP_GPIO_CAP_EN, tmp); 3179 + 3180 + /* Disable interrupt top interrupt */ 3181 + tmp = lanphy_read_page_reg(phydev, 4, PTP_COMMON_INT_ENA); 3182 + tmp &= ~PTP_COMMON_INT_ENA_GPIO_CAP_EN; 3183 + lanphy_write_page_reg(phydev, 4, PTP_COMMON_INT_ENA, tmp); 3184 + } 3185 + 3186 + static int lan8814_ptp_extts(struct ptp_clock_info *ptpci, 3187 + struct ptp_clock_request *rq, int on) 3188 + { 3189 + struct lan8814_shared_priv *shared = container_of(ptpci, struct lan8814_shared_priv, 3190 + ptp_clock_info); 3191 + struct phy_device *phydev = shared->phydev; 3192 + int pin; 3193 + 3194 + if (rq->extts.flags & ~(PTP_ENABLE_FEATURE | 3195 + PTP_EXTTS_EDGES | 3196 + PTP_STRICT_FLAGS)) 3197 + return -EOPNOTSUPP; 3198 + 3199 + pin = ptp_find_pin(shared->ptp_clock, PTP_PF_EXTTS, 3200 + rq->extts.index); 3201 + if (pin == -1 || pin != LAN8814_PTP_EXTTS_NUM) 3202 + return -EINVAL; 3203 + 3204 + mutex_lock(&shared->shared_lock); 3205 + if (on) 3206 + lan8814_ptp_extts_on(phydev, pin, rq->extts.flags); 3207 + else 3208 + lan8814_ptp_extts_off(phydev, pin); 3209 + 3210 + mutex_unlock(&shared->shared_lock); 3211 + 3212 + return 0; 3213 + } 3214 + 3152 3215 static int lan8814_ptpci_enable(struct ptp_clock_info *ptpci, 3153 3216 struct ptp_clock_request *rq, int on) 3154 3217 { 3155 3218 switch (rq->type) { 3156 3219 case PTP_CLK_REQ_PEROUT: 3157 3220 return lan8814_ptp_perout(ptpci, rq, on); 3221 + case PTP_CLK_REQ_EXTTS: 3222 + return lan8814_ptp_extts(ptpci, rq, on); 3158 3223 default: 3159 3224 return -EINVAL; 3160 3225 } ··· 3261 3146 * chan 1 (event B) 3262 3147 */ 3263 3148 if (pin >= LAN8814_PTP_PEROUT_NUM || pin != chan) 3149 + return -1; 3150 + break; 3151 + case PTP_PF_EXTTS: 3152 + if (pin != LAN8814_PTP_EXTTS_NUM) 3264 3153 return -1; 3265 3154 break; 3266 3155 default: ··· 3439 3320 } 3440 3321 } 3441 3322 3323 + static int lan8814_gpio_process_cap(struct lan8814_shared_priv *shared) 3324 + { 3325 + struct phy_device *phydev = shared->phydev; 3326 + struct ptp_clock_event ptp_event = {0}; 3327 + unsigned long nsec; 3328 + s64 sec; 3329 + u16 tmp; 3330 + 3331 + /* This is 0 because whatever was the input pin it was mapped it to 3332 + * ltc gpio pin 0 3333 + */ 3334 + tmp = lanphy_read_page_reg(phydev, 4, PTP_GPIO_SEL); 3335 + tmp |= PTP_GPIO_SEL_GPIO_SEL(0); 3336 + lanphy_write_page_reg(phydev, 4, PTP_GPIO_SEL, tmp); 3337 + 3338 + tmp = lanphy_read_page_reg(phydev, 4, PTP_GPIO_CAP_STS); 3339 + if (!(tmp & PTP_GPIO_CAP_STS_PTP_GPIO_RE_STS(0)) && 3340 + !(tmp & PTP_GPIO_CAP_STS_PTP_GPIO_FE_STS(0))) 3341 + return -1; 3342 + 3343 + if (tmp & BIT(0)) { 3344 + sec = lanphy_read_page_reg(phydev, 4, PTP_GPIO_RE_LTC_SEC_HI_CAP); 3345 + sec <<= 16; 3346 + sec |= lanphy_read_page_reg(phydev, 4, PTP_GPIO_RE_LTC_SEC_LO_CAP); 3347 + 3348 + nsec = lanphy_read_page_reg(phydev, 4, PTP_GPIO_RE_LTC_NS_HI_CAP) & 0x3fff; 3349 + nsec <<= 16; 3350 + nsec |= lanphy_read_page_reg(phydev, 4, PTP_GPIO_RE_LTC_NS_LO_CAP); 3351 + } else { 3352 + sec = lanphy_read_page_reg(phydev, 4, PTP_GPIO_FE_LTC_SEC_HI_CAP); 3353 + sec <<= 16; 3354 + sec |= lanphy_read_page_reg(phydev, 4, PTP_GPIO_FE_LTC_SEC_LO_CAP); 3355 + 3356 + nsec = lanphy_read_page_reg(phydev, 4, PTP_GPIO_FE_LTC_NS_HI_CAP) & 0x3fff; 3357 + nsec <<= 16; 3358 + nsec |= lanphy_read_page_reg(phydev, 4, PTP_GPIO_RE_LTC_NS_LO_CAP); 3359 + } 3360 + 3361 + ptp_event.index = 0; 3362 + ptp_event.timestamp = ktime_set(sec, nsec); 3363 + ptp_event.type = PTP_CLOCK_EXTTS; 3364 + ptp_clock_event(shared->ptp_clock, &ptp_event); 3365 + 3366 + return 0; 3367 + } 3368 + 3369 + static int lan8814_handle_gpio_interrupt(struct phy_device *phydev, u16 status) 3370 + { 3371 + struct lan8814_shared_priv *shared = phydev->shared->priv; 3372 + int ret; 3373 + 3374 + mutex_lock(&shared->shared_lock); 3375 + ret = lan8814_gpio_process_cap(shared); 3376 + mutex_unlock(&shared->shared_lock); 3377 + 3378 + return ret; 3379 + } 3380 + 3442 3381 static int lan8804_config_init(struct phy_device *phydev) 3443 3382 { 3444 3383 int val; ··· 3600 3423 lan8814_handle_ptp_interrupt(phydev, irq_status); 3601 3424 ret = IRQ_HANDLED; 3602 3425 } 3426 + 3427 + if (!lan8814_handle_gpio_interrupt(phydev, irq_status)) 3428 + ret = IRQ_HANDLED; 3603 3429 3604 3430 return ret; 3605 3431 } ··· 3721 3541 snprintf(shared->ptp_clock_info.name, 30, "%s", phydev->drv->name); 3722 3542 shared->ptp_clock_info.max_adj = 31249999; 3723 3543 shared->ptp_clock_info.n_alarm = 0; 3724 - shared->ptp_clock_info.n_ext_ts = 0; 3544 + shared->ptp_clock_info.n_ext_ts = LAN8814_PTP_EXTTS_NUM; 3725 3545 shared->ptp_clock_info.n_pins = LAN8814_PTP_GPIO_NUM; 3726 3546 shared->ptp_clock_info.pps = 0; 3727 3547 shared->ptp_clock_info.pin_config = shared->pin_config;