Commit 930dfa56 authored by Min Li's avatar Min Li Committed by David S. Miller

ptp: clockmatrix: use rsmu driver to access i2c/spi bus

rsmu (Renesas Synchronization Management Unit ) driver is located in
drivers/mfd and responsible for creating multiple devices including
clockmatrix phc, which will then use the exposed regmap and mutex
handle to access i2c/spi bus.
Signed-off-by: default avatarMin Li <min.li.xe@renesas.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b69c9946
/* SPDX-License-Identifier: GPL-2.0+ */
/* idt8a340_reg.h
*
* Originally generated by regen.tcl on Thu Feb 14 19:23:44 PST 2019
* https://github.com/richardcochran/regen
*
* Hand modified to include some HW registers.
* Based on 5.2.0, Family Programming Guide (Sept 30, 2020)
*/
#ifndef HAVE_IDT8A340_REG
#define HAVE_IDT8A340_REG
#define PAGE_ADDR_BASE 0x0000
#define PAGE_ADDR 0x00fc
#define HW_REVISION 0x8180
#define REV_ID 0x007a
#define HW_DPLL_0 (0x8a00)
#define HW_DPLL_1 (0x8b00)
#define HW_DPLL_2 (0x8c00)
#define HW_DPLL_3 (0x8d00)
#define HW_DPLL_4 (0x8e00)
#define HW_DPLL_5 (0x8f00)
#define HW_DPLL_6 (0x9000)
#define HW_DPLL_7 (0x9100)
#define HW_DPLL_TOD_SW_TRIG_ADDR__0 (0x080)
#define HW_DPLL_TOD_CTRL_1 (0x089)
#define HW_DPLL_TOD_CTRL_2 (0x08A)
#define HW_DPLL_TOD_OVR__0 (0x098)
#define HW_DPLL_TOD_OUT_0__0 (0x0B0)
#define HW_Q0_Q1_CH_SYNC_CTRL_0 (0xa740)
#define HW_Q0_Q1_CH_SYNC_CTRL_1 (0xa741)
#define HW_Q2_Q3_CH_SYNC_CTRL_0 (0xa742)
#define HW_Q2_Q3_CH_SYNC_CTRL_1 (0xa743)
#define HW_Q4_Q5_CH_SYNC_CTRL_0 (0xa744)
#define HW_Q4_Q5_CH_SYNC_CTRL_1 (0xa745)
#define HW_Q6_Q7_CH_SYNC_CTRL_0 (0xa746)
#define HW_Q6_Q7_CH_SYNC_CTRL_1 (0xa747)
#define HW_Q8_CH_SYNC_CTRL_0 (0xa748)
#define HW_Q8_CH_SYNC_CTRL_1 (0xa749)
#define HW_Q9_CH_SYNC_CTRL_0 (0xa74a)
#define HW_Q9_CH_SYNC_CTRL_1 (0xa74b)
#define HW_Q10_CH_SYNC_CTRL_0 (0xa74c)
#define HW_Q10_CH_SYNC_CTRL_1 (0xa74d)
#define HW_Q11_CH_SYNC_CTRL_0 (0xa74e)
#define HW_Q11_CH_SYNC_CTRL_1 (0xa74f)
#define SYNC_SOURCE_DPLL0_TOD_PPS 0x14
#define SYNC_SOURCE_DPLL1_TOD_PPS 0x15
#define SYNC_SOURCE_DPLL2_TOD_PPS 0x16
#define SYNC_SOURCE_DPLL3_TOD_PPS 0x17
#define SYNCTRL1_MASTER_SYNC_RST BIT(7)
#define SYNCTRL1_MASTER_SYNC_TRIG BIT(5)
#define SYNCTRL1_TOD_SYNC_TRIG BIT(4)
#define SYNCTRL1_FBDIV_FRAME_SYNC_TRIG BIT(3)
#define SYNCTRL1_FBDIV_SYNC_TRIG BIT(2)
#define SYNCTRL1_Q1_DIV_SYNC_TRIG BIT(1)
#define SYNCTRL1_Q0_DIV_SYNC_TRIG BIT(0)
#define HW_Q8_CTRL_SPARE (0xa7d4)
#define HW_Q11_CTRL_SPARE (0xa7ec)
/**
* Select FOD5 as sync_trigger for Q8 divider.
* Transition from logic zero to one
* sets trigger to sync Q8 divider.
*
* Unused when FOD4 is driving Q8 divider (normal operation).
*/
#define Q9_TO_Q8_SYNC_TRIG BIT(1)
/**
* Enable FOD5 as driver for clock and sync for Q8 divider.
* Enable fanout buffer for FOD5.
*
* Unused when FOD4 is driving Q8 divider (normal operation).
*/
#define Q9_TO_Q8_FANOUT_AND_CLOCK_SYNC_ENABLE_MASK (BIT(0) | BIT(2))
/**
* Select FOD6 as sync_trigger for Q11 divider.
* Transition from logic zero to one
* sets trigger to sync Q11 divider.
*
* Unused when FOD7 is driving Q11 divider (normal operation).
*/
#define Q10_TO_Q11_SYNC_TRIG BIT(1)
/**
* Enable FOD6 as driver for clock and sync for Q11 divider.
* Enable fanout buffer for FOD6.
*
* Unused when FOD7 is driving Q11 divider (normal operation).
*/
#define Q10_TO_Q11_FANOUT_AND_CLOCK_SYNC_ENABLE_MASK (BIT(0) | BIT(2))
#define RESET_CTRL 0xc000
#define SM_RESET 0x0012
#define SM_RESET_V520 0x0013
#define SM_RESET_CMD 0x5A
#define GENERAL_STATUS 0xc014
#define BOOT_STATUS 0x0000
#define HW_REV_ID 0x000A
#define BOND_ID 0x000B
#define HW_CSR_ID 0x000C
#define HW_IRQ_ID 0x000E
#define MAJ_REL 0x0010
#define MIN_REL 0x0011
#define HOTFIX_REL 0x0012
#define PIPELINE_ID 0x0014
#define BUILD_ID 0x0018
#define JTAG_DEVICE_ID 0x001c
#define PRODUCT_ID 0x001e
#define OTP_SCSR_CONFIG_SELECT 0x0022
#define STATUS 0xc03c
#define DPLL_SYS_STATUS 0x0020
#define DPLL_SYS_APLL_STATUS 0x0021
#define USER_GPIO0_TO_7_STATUS 0x008a
#define USER_GPIO8_TO_15_STATUS 0x008b
#define GPIO_USER_CONTROL 0xc160
#define GPIO0_TO_7_OUT 0x0000
#define GPIO8_TO_15_OUT 0x0001
#define GPIO0_TO_7_OUT_V520 0x0002
#define GPIO8_TO_15_OUT_V520 0x0003
#define STICKY_STATUS_CLEAR 0xc164
#define GPIO_TOD_NOTIFICATION_CLEAR 0xc16c
#define ALERT_CFG 0xc188
#define SYS_DPLL_XO 0xc194
#define SYS_APLL 0xc19c
#define INPUT_0 0xc1b0
#define INPUT_1 0xc1c0
#define INPUT_2 0xc1d0
#define INPUT_3 0xc200
#define INPUT_4 0xc210
#define INPUT_5 0xc220
#define INPUT_6 0xc230
#define INPUT_7 0xc240
#define INPUT_8 0xc250
#define INPUT_9 0xc260
#define INPUT_10 0xc280
#define INPUT_11 0xc290
#define INPUT_12 0xc2a0
#define INPUT_13 0xc2b0
#define INPUT_14 0xc2c0
#define INPUT_15 0xc2d0
#define REF_MON_0 0xc2e0
#define REF_MON_1 0xc2ec
#define REF_MON_2 0xc300
#define REF_MON_3 0xc30c
#define REF_MON_4 0xc318
#define REF_MON_5 0xc324
#define REF_MON_6 0xc330
#define REF_MON_7 0xc33c
#define REF_MON_8 0xc348
#define REF_MON_9 0xc354
#define REF_MON_10 0xc360
#define REF_MON_11 0xc36c
#define REF_MON_12 0xc380
#define REF_MON_13 0xc38c
#define REF_MON_14 0xc398
#define REF_MON_15 0xc3a4
#define DPLL_0 0xc3b0
#define DPLL_CTRL_REG_0 0x0002
#define DPLL_CTRL_REG_1 0x0003
#define DPLL_CTRL_REG_2 0x0004
#define DPLL_TOD_SYNC_CFG 0x0031
#define DPLL_COMBO_SLAVE_CFG_0 0x0032
#define DPLL_COMBO_SLAVE_CFG_1 0x0033
#define DPLL_SLAVE_REF_CFG 0x0034
#define DPLL_REF_MODE 0x0035
#define DPLL_PHASE_MEASUREMENT_CFG 0x0036
#define DPLL_MODE 0x0037
#define DPLL_MODE_V520 0x003B
#define DPLL_1 0xc400
#define DPLL_2 0xc438
#define DPLL_2_V520 0xc43c
#define DPLL_3 0xc480
#define DPLL_4 0xc4b8
#define DPLL_4_V520 0xc4bc
#define DPLL_5 0xc500
#define DPLL_6 0xc538
#define DPLL_6_V520 0xc53c
#define DPLL_7 0xc580
#define SYS_DPLL 0xc5b8
#define SYS_DPLL_V520 0xc5bc
#define DPLL_CTRL_0 0xc600
#define DPLL_CTRL_DPLL_MANU_REF_CFG 0x0001
#define DPLL_CTRL_COMBO_MASTER_CFG 0x003a
#define DPLL_CTRL_1 0xc63c
#define DPLL_CTRL_2 0xc680
#define DPLL_CTRL_3 0xc6bc
#define DPLL_CTRL_4 0xc700
#define DPLL_CTRL_5 0xc73c
#define DPLL_CTRL_6 0xc780
#define DPLL_CTRL_7 0xc7bc
#define SYS_DPLL_CTRL 0xc800
#define DPLL_PHASE_0 0xc818
/* Signed 42-bit FFO in units of 2^(-53) */
#define DPLL_WR_PHASE 0x0000
#define DPLL_PHASE_1 0xc81c
#define DPLL_PHASE_2 0xc820
#define DPLL_PHASE_3 0xc824
#define DPLL_PHASE_4 0xc828
#define DPLL_PHASE_5 0xc82c
#define DPLL_PHASE_6 0xc830
#define DPLL_PHASE_7 0xc834
#define DPLL_FREQ_0 0xc838
/* Signed 42-bit FFO in units of 2^(-53) */
#define DPLL_WR_FREQ 0x0000
#define DPLL_FREQ_1 0xc840
#define DPLL_FREQ_2 0xc848
#define DPLL_FREQ_3 0xc850
#define DPLL_FREQ_4 0xc858
#define DPLL_FREQ_5 0xc860
#define DPLL_FREQ_6 0xc868
#define DPLL_FREQ_7 0xc870
#define DPLL_PHASE_PULL_IN_0 0xc880
#define PULL_IN_OFFSET 0x0000 /* Signed 32 bit */
#define PULL_IN_SLOPE_LIMIT 0x0004 /* Unsigned 24 bit */
#define PULL_IN_CTRL 0x0007
#define DPLL_PHASE_PULL_IN_1 0xc888
#define DPLL_PHASE_PULL_IN_2 0xc890
#define DPLL_PHASE_PULL_IN_3 0xc898
#define DPLL_PHASE_PULL_IN_4 0xc8a0
#define DPLL_PHASE_PULL_IN_5 0xc8a8
#define DPLL_PHASE_PULL_IN_6 0xc8b0
#define DPLL_PHASE_PULL_IN_7 0xc8b8
#define GPIO_CFG 0xc8c0
#define GPIO_CFG_GBL 0x0000
#define GPIO_0 0xc8c2
#define GPIO_DCO_INC_DEC 0x0000
#define GPIO_OUT_CTRL_0 0x0001
#define GPIO_OUT_CTRL_1 0x0002
#define GPIO_TOD_TRIG 0x0003
#define GPIO_DPLL_INDICATOR 0x0004
#define GPIO_LOS_INDICATOR 0x0005
#define GPIO_REF_INPUT_DSQ_0 0x0006
#define GPIO_REF_INPUT_DSQ_1 0x0007
#define GPIO_REF_INPUT_DSQ_2 0x0008
#define GPIO_REF_INPUT_DSQ_3 0x0009
#define GPIO_MAN_CLK_SEL_0 0x000a
#define GPIO_MAN_CLK_SEL_1 0x000b
#define GPIO_MAN_CLK_SEL_2 0x000c
#define GPIO_SLAVE 0x000d
#define GPIO_ALERT_OUT_CFG 0x000e
#define GPIO_TOD_NOTIFICATION_CFG 0x000f
#define GPIO_CTRL 0x0010
#define GPIO_CTRL_V520 0x0011
#define GPIO_1 0xc8d4
#define GPIO_2 0xc8e6
#define GPIO_3 0xc900
#define GPIO_4 0xc912
#define GPIO_5 0xc924
#define GPIO_6 0xc936
#define GPIO_7 0xc948
#define GPIO_8 0xc95a
#define GPIO_9 0xc980
#define GPIO_10 0xc992
#define GPIO_11 0xc9a4
#define GPIO_12 0xc9b6
#define GPIO_13 0xc9c8
#define GPIO_14 0xc9da
#define GPIO_15 0xca00
#define OUT_DIV_MUX 0xca12
#define OUTPUT_0 0xca14
#define OUTPUT_0_V520 0xca20
/* FOD frequency output divider value */
#define OUT_DIV 0x0000
#define OUT_DUTY_CYCLE_HIGH 0x0004
#define OUT_CTRL_0 0x0008
#define OUT_CTRL_1 0x0009
/* Phase adjustment in FOD cycles */
#define OUT_PHASE_ADJ 0x000c
#define OUTPUT_1 0xca24
#define OUTPUT_1_V520 0xca30
#define OUTPUT_2 0xca34
#define OUTPUT_2_V520 0xca40
#define OUTPUT_3 0xca44
#define OUTPUT_3_V520 0xca50
#define OUTPUT_4 0xca54
#define OUTPUT_4_V520 0xca60
#define OUTPUT_5 0xca64
#define OUTPUT_5_V520 0xca80
#define OUTPUT_6 0xca80
#define OUTPUT_6_V520 0xca90
#define OUTPUT_7 0xca90
#define OUTPUT_7_V520 0xcaa0
#define OUTPUT_8 0xcaa0
#define OUTPUT_8_V520 0xcab0
#define OUTPUT_9 0xcab0
#define OUTPUT_9_V520 0xcac0
#define OUTPUT_10 0xcac0
#define OUTPUT_10_V520 0xcad0
#define OUTPUT_11 0xcad0
#define OUTPUT_11_V520 0xcae0
#define SERIAL 0xcae0
#define SERIAL_V520 0xcaf0
#define PWM_ENCODER_0 0xcb00
#define PWM_ENCODER_1 0xcb08
#define PWM_ENCODER_2 0xcb10
#define PWM_ENCODER_3 0xcb18
#define PWM_ENCODER_4 0xcb20
#define PWM_ENCODER_5 0xcb28
#define PWM_ENCODER_6 0xcb30
#define PWM_ENCODER_7 0xcb38
#define PWM_DECODER_0 0xcb40
#define PWM_DECODER_1 0xcb48
#define PWM_DECODER_1_V520 0xcb4a
#define PWM_DECODER_2 0xcb50
#define PWM_DECODER_2_V520 0xcb54
#define PWM_DECODER_3 0xcb58
#define PWM_DECODER_3_V520 0xcb5e
#define PWM_DECODER_4 0xcb60
#define PWM_DECODER_4_V520 0xcb68
#define PWM_DECODER_5 0xcb68
#define PWM_DECODER_5_V520 0xcb80
#define PWM_DECODER_6 0xcb70
#define PWM_DECODER_6_V520 0xcb8a
#define PWM_DECODER_7 0xcb80
#define PWM_DECODER_7_V520 0xcb94
#define PWM_DECODER_8 0xcb88
#define PWM_DECODER_8_V520 0xcb9e
#define PWM_DECODER_9 0xcb90
#define PWM_DECODER_9_V520 0xcba8
#define PWM_DECODER_10 0xcb98
#define PWM_DECODER_10_V520 0xcbb2
#define PWM_DECODER_11 0xcba0
#define PWM_DECODER_11_V520 0xcbbc
#define PWM_DECODER_12 0xcba8
#define PWM_DECODER_12_V520 0xcbc6
#define PWM_DECODER_13 0xcbb0
#define PWM_DECODER_13_V520 0xcbd0
#define PWM_DECODER_14 0xcbb8
#define PWM_DECODER_14_V520 0xcbda
#define PWM_DECODER_15 0xcbc0
#define PWM_DECODER_15_V520 0xcbe4
#define PWM_USER_DATA 0xcbc8
#define PWM_USER_DATA_V520 0xcbf0
#define TOD_0 0xcbcc
#define TOD_0_V520 0xcc00
/* Enable TOD counter, output channel sync and even-PPS mode */
#define TOD_CFG 0x0000
#define TOD_CFG_V520 0x0001
#define TOD_1 0xcbce
#define TOD_1_V520 0xcc02
#define TOD_2 0xcbd0
#define TOD_2_V520 0xcc04
#define TOD_3 0xcbd2
#define TOD_3_V520 0xcc06
#define TOD_WRITE_0 0xcc00
#define TOD_WRITE_0_V520 0xcc10
/* 8-bit subns, 32-bit ns, 48-bit seconds */
#define TOD_WRITE 0x0000
/* Counter increments after TOD write is completed */
#define TOD_WRITE_COUNTER 0x000c
/* TOD write trigger configuration */
#define TOD_WRITE_SELECT_CFG_0 0x000d
/* TOD write trigger selection */
#define TOD_WRITE_CMD 0x000f
#define TOD_WRITE_1 0xcc10
#define TOD_WRITE_1_V520 0xcc20
#define TOD_WRITE_2 0xcc20
#define TOD_WRITE_2_V520 0xcc30
#define TOD_WRITE_3 0xcc30
#define TOD_WRITE_3_V520 0xcc40
#define TOD_READ_PRIMARY_0 0xcc40
#define TOD_READ_PRIMARY_0_V520 0xcc50
/* 8-bit subns, 32-bit ns, 48-bit seconds */
#define TOD_READ_PRIMARY 0x0000
/* Counter increments after TOD write is completed */
#define TOD_READ_PRIMARY_COUNTER 0x000b
/* Read trigger configuration */
#define TOD_READ_PRIMARY_SEL_CFG_0 0x000c
/* Read trigger selection */
#define TOD_READ_PRIMARY_CMD 0x000e
#define TOD_READ_PRIMARY_CMD_V520 0x000f
#define TOD_READ_PRIMARY_1 0xcc50
#define TOD_READ_PRIMARY_1_V520 0xcc60
#define TOD_READ_PRIMARY_2 0xcc60
#define TOD_READ_PRIMARY_2_V520 0xcc80
#define TOD_READ_PRIMARY_3 0xcc80
#define TOD_READ_PRIMARY_3_V520 0xcc90
#define TOD_READ_SECONDARY_0 0xcc90
#define TOD_READ_SECONDARY_0_V520 0xcca0
#define TOD_READ_SECONDARY_1 0xcca0
#define TOD_READ_SECONDARY_1_V520 0xccb0
#define TOD_READ_SECONDARY_2 0xccb0
#define TOD_READ_SECONDARY_2_V520 0xccc0
#define TOD_READ_SECONDARY_3 0xccc0
#define TOD_READ_SECONDARY_3_V520 0xccd0
#define OUTPUT_TDC_CFG 0xccd0
#define OUTPUT_TDC_CFG_V520 0xcce0
#define OUTPUT_TDC_0 0xcd00
#define OUTPUT_TDC_1 0xcd08
#define OUTPUT_TDC_2 0xcd10
#define OUTPUT_TDC_3 0xcd18
#define INPUT_TDC 0xcd20
#define SCRATCH 0xcf50
#define SCRATCH_V520 0xcf4c
#define EEPROM 0xcf68
#define EEPROM_V520 0xcf64
#define OTP 0xcf70
#define BYTE 0xcf80
/* Bit definitions for the MAJ_REL register */
#define MAJOR_SHIFT (1)
#define MAJOR_MASK (0x7f)
#define PR_BUILD BIT(0)
/* Bit definitions for the USER_GPIO0_TO_7_STATUS register */
#define GPIO0_LEVEL BIT(0)
#define GPIO1_LEVEL BIT(1)
#define GPIO2_LEVEL BIT(2)
#define GPIO3_LEVEL BIT(3)
#define GPIO4_LEVEL BIT(4)
#define GPIO5_LEVEL BIT(5)
#define GPIO6_LEVEL BIT(6)
#define GPIO7_LEVEL BIT(7)
/* Bit definitions for the USER_GPIO8_TO_15_STATUS register */
#define GPIO8_LEVEL BIT(0)
#define GPIO9_LEVEL BIT(1)
#define GPIO10_LEVEL BIT(2)
#define GPIO11_LEVEL BIT(3)
#define GPIO12_LEVEL BIT(4)
#define GPIO13_LEVEL BIT(5)
#define GPIO14_LEVEL BIT(6)
#define GPIO15_LEVEL BIT(7)
/* Bit definitions for the GPIO0_TO_7_OUT register */
#define GPIO0_DRIVE_LEVEL BIT(0)
#define GPIO1_DRIVE_LEVEL BIT(1)
#define GPIO2_DRIVE_LEVEL BIT(2)
#define GPIO3_DRIVE_LEVEL BIT(3)
#define GPIO4_DRIVE_LEVEL BIT(4)
#define GPIO5_DRIVE_LEVEL BIT(5)
#define GPIO6_DRIVE_LEVEL BIT(6)
#define GPIO7_DRIVE_LEVEL BIT(7)
/* Bit definitions for the GPIO8_TO_15_OUT register */
#define GPIO8_DRIVE_LEVEL BIT(0)
#define GPIO9_DRIVE_LEVEL BIT(1)
#define GPIO10_DRIVE_LEVEL BIT(2)
#define GPIO11_DRIVE_LEVEL BIT(3)
#define GPIO12_DRIVE_LEVEL BIT(4)
#define GPIO13_DRIVE_LEVEL BIT(5)
#define GPIO14_DRIVE_LEVEL BIT(6)
#define GPIO15_DRIVE_LEVEL BIT(7)
/* Bit definitions for the DPLL_TOD_SYNC_CFG register */
#define TOD_SYNC_SOURCE_SHIFT (1)
#define TOD_SYNC_SOURCE_MASK (0x3)
#define TOD_SYNC_EN BIT(0)
/* Bit definitions for the DPLL_MODE register */
#define WRITE_TIMER_MODE BIT(6)
#define PLL_MODE_SHIFT (3)
#define PLL_MODE_MASK (0x7)
#define STATE_MODE_SHIFT (0)
#define STATE_MODE_MASK (0x7)
/* Bit definitions for the DPLL_MANU_REF_CFG register */
#define MANUAL_REFERENCE_SHIFT (0)
#define MANUAL_REFERENCE_MASK (0x1f)
/* Bit definitions for the GPIO_CFG_GBL register */
#define SUPPLY_MODE_SHIFT (0)
#define SUPPLY_MODE_MASK (0x3)
/* Bit definitions for the GPIO_DCO_INC_DEC register */
#define INCDEC_DPLL_INDEX_SHIFT (0)
#define INCDEC_DPLL_INDEX_MASK (0x7)
/* Bit definitions for the GPIO_OUT_CTRL_0 register */
#define CTRL_OUT_0 BIT(0)
#define CTRL_OUT_1 BIT(1)
#define CTRL_OUT_2 BIT(2)
#define CTRL_OUT_3 BIT(3)
#define CTRL_OUT_4 BIT(4)
#define CTRL_OUT_5 BIT(5)
#define CTRL_OUT_6 BIT(6)
#define CTRL_OUT_7 BIT(7)
/* Bit definitions for the GPIO_OUT_CTRL_1 register */
#define CTRL_OUT_8 BIT(0)
#define CTRL_OUT_9 BIT(1)
#define CTRL_OUT_10 BIT(2)
#define CTRL_OUT_11 BIT(3)
#define CTRL_OUT_12 BIT(4)
#define CTRL_OUT_13 BIT(5)
#define CTRL_OUT_14 BIT(6)
#define CTRL_OUT_15 BIT(7)
/* Bit definitions for the GPIO_TOD_TRIG register */
#define TOD_TRIG_0 BIT(0)
#define TOD_TRIG_1 BIT(1)
#define TOD_TRIG_2 BIT(2)
#define TOD_TRIG_3 BIT(3)
/* Bit definitions for the GPIO_DPLL_INDICATOR register */
#define IND_DPLL_INDEX_SHIFT (0)
#define IND_DPLL_INDEX_MASK (0x7)
/* Bit definitions for the GPIO_LOS_INDICATOR register */
#define REFMON_INDEX_SHIFT (0)
#define REFMON_INDEX_MASK (0xf)
/* Active level of LOS indicator, 0=low 1=high */
#define ACTIVE_LEVEL BIT(4)
/* Bit definitions for the GPIO_REF_INPUT_DSQ_0 register */
#define DSQ_INP_0 BIT(0)
#define DSQ_INP_1 BIT(1)
#define DSQ_INP_2 BIT(2)
#define DSQ_INP_3 BIT(3)
#define DSQ_INP_4 BIT(4)
#define DSQ_INP_5 BIT(5)
#define DSQ_INP_6 BIT(6)
#define DSQ_INP_7 BIT(7)
/* Bit definitions for the GPIO_REF_INPUT_DSQ_1 register */
#define DSQ_INP_8 BIT(0)
#define DSQ_INP_9 BIT(1)
#define DSQ_INP_10 BIT(2)
#define DSQ_INP_11 BIT(3)
#define DSQ_INP_12 BIT(4)
#define DSQ_INP_13 BIT(5)
#define DSQ_INP_14 BIT(6)
#define DSQ_INP_15 BIT(7)
/* Bit definitions for the GPIO_REF_INPUT_DSQ_2 register */
#define DSQ_DPLL_0 BIT(0)
#define DSQ_DPLL_1 BIT(1)
#define DSQ_DPLL_2 BIT(2)
#define DSQ_DPLL_3 BIT(3)
#define DSQ_DPLL_4 BIT(4)
#define DSQ_DPLL_5 BIT(5)
#define DSQ_DPLL_6 BIT(6)
#define DSQ_DPLL_7 BIT(7)
/* Bit definitions for the GPIO_REF_INPUT_DSQ_3 register */
#define DSQ_DPLL_SYS BIT(0)
#define GPIO_DSQ_LEVEL BIT(1)
/* Bit definitions for the GPIO_TOD_NOTIFICATION_CFG register */
#define DPLL_TOD_SHIFT (0)
#define DPLL_TOD_MASK (0x3)
#define TOD_READ_SECONDARY BIT(2)
#define GPIO_ASSERT_LEVEL BIT(3)
/* Bit definitions for the GPIO_CTRL register */
#define GPIO_FUNCTION_EN BIT(0)
#define GPIO_CMOS_OD_MODE BIT(1)
#define GPIO_CONTROL_DIR BIT(2)
#define GPIO_PU_PD_MODE BIT(3)
#define GPIO_FUNCTION_SHIFT (4)
#define GPIO_FUNCTION_MASK (0xf)
/* Bit definitions for the OUT_CTRL_1 register */
#define OUT_SYNC_DISABLE BIT(7)
#define SQUELCH_VALUE BIT(6)
#define SQUELCH_DISABLE BIT(5)
#define PAD_VDDO_SHIFT (2)
#define PAD_VDDO_MASK (0x7)
#define PAD_CMOSDRV_SHIFT (0)
#define PAD_CMOSDRV_MASK (0x3)
/* Bit definitions for the TOD_CFG register */
#define TOD_EVEN_PPS_MODE BIT(2)
#define TOD_OUT_SYNC_ENABLE BIT(1)
#define TOD_ENABLE BIT(0)
/* Bit definitions for the TOD_WRITE_SELECT_CFG_0 register */
#define WR_PWM_DECODER_INDEX_SHIFT (4)
#define WR_PWM_DECODER_INDEX_MASK (0xf)
#define WR_REF_INDEX_SHIFT (0)
#define WR_REF_INDEX_MASK (0xf)
/* Bit definitions for the TOD_WRITE_CMD register */
#define TOD_WRITE_SELECTION_SHIFT (0)
#define TOD_WRITE_SELECTION_MASK (0xf)
/* 4.8.7 */
#define TOD_WRITE_TYPE_SHIFT (4)
#define TOD_WRITE_TYPE_MASK (0x3)
/* Bit definitions for the TOD_READ_PRIMARY_SEL_CFG_0 register */
#define RD_PWM_DECODER_INDEX_SHIFT (4)
#define RD_PWM_DECODER_INDEX_MASK (0xf)
#define RD_REF_INDEX_SHIFT (0)
#define RD_REF_INDEX_MASK (0xf)
/* Bit definitions for the TOD_READ_PRIMARY_CMD register */
#define TOD_READ_TRIGGER_MODE BIT(4)
#define TOD_READ_TRIGGER_SHIFT (0)
#define TOD_READ_TRIGGER_MASK (0xf)
/* Bit definitions for the DPLL_CTRL_COMBO_MASTER_CFG register */
#define COMBO_MASTER_HOLD BIT(0)
/* Bit definitions for DPLL_SYS_STATUS register */
#define DPLL_SYS_STATE_MASK (0xf)
/* Bit definitions for SYS_APLL_STATUS register */
#define SYS_APLL_LOSS_LOCK_LIVE_MASK BIT(0)
#define SYS_APLL_LOSS_LOCK_LIVE_LOCKED 0
#define SYS_APLL_LOSS_LOCK_LIVE_UNLOCKED 1
#endif
......@@ -6,7 +6,7 @@
* Copyright (C) 2019 Integrated Device Technology, Inc., a Renesas Company.
*/
#include <linux/firmware.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/ptp_clock_kernel.h>
#include <linux/delay.h>
......@@ -14,6 +14,10 @@
#include <linux/kernel.h>
#include <linux/timekeeping.h>
#include <linux/string.h>
#include <linux/of.h>
#include <linux/mfd/rsmu.h>
#include <linux/mfd/idt8a340_reg.h>
#include <asm/unaligned.h>
#include "ptp_private.h"
#include "ptp_clockmatrix.h"
......@@ -32,9 +36,28 @@ static char *firmware;
module_param(firmware, charp, 0);
#define SETTIME_CORRECTION (0)
#define EXTTS_PERIOD_MS (95)
static int _idtcm_adjfine(struct idtcm_channel *channel, long scaled_ppm);
static inline int idtcm_read(struct idtcm *idtcm,
u16 module,
u16 regaddr,
u8 *buf,
u16 count)
{
return regmap_bulk_read(idtcm->regmap, module + regaddr, buf, count);
}
static inline int idtcm_write(struct idtcm *idtcm,
u16 module,
u16 regaddr,
u8 *buf,
u16 count)
{
return regmap_bulk_write(idtcm->regmap, module + regaddr, buf, count);
}
static int contains_full_configuration(struct idtcm *idtcm,
const struct firmware *fw)
{
......@@ -173,134 +196,6 @@ static enum fw_version idtcm_fw_version(const char *version)
return ver;
}
static int idtcm_xfer_read(struct idtcm *idtcm,
u8 regaddr,
u8 *buf,
u16 count)
{
struct i2c_client *client = idtcm->client;
struct i2c_msg msg[2];
int cnt;
msg[0].addr = client->addr;
msg[0].flags = 0;
msg[0].len = 1;
msg[0].buf = &regaddr;
msg[1].addr = client->addr;
msg[1].flags = I2C_M_RD;
msg[1].len = count;
msg[1].buf = buf;
cnt = i2c_transfer(client->adapter, msg, 2);
if (cnt < 0) {
dev_err(&client->dev,
"i2c_transfer failed at %d in %s, at addr: %04x!",
__LINE__, __func__, regaddr);
return cnt;
} else if (cnt != 2) {
dev_err(&client->dev,
"i2c_transfer sent only %d of %d messages", cnt, 2);
return -EIO;
}
return 0;
}
static int idtcm_xfer_write(struct idtcm *idtcm,
u8 regaddr,
u8 *buf,
u16 count)
{
struct i2c_client *client = idtcm->client;
/* we add 1 byte for device register */
u8 msg[IDTCM_MAX_WRITE_COUNT + 1];
int cnt;
if (count > IDTCM_MAX_WRITE_COUNT)
return -EINVAL;
msg[0] = regaddr;
memcpy(&msg[1], buf, count);
cnt = i2c_master_send(client, msg, count + 1);
if (cnt < 0) {
dev_err(&client->dev,
"i2c_master_send failed at %d in %s, at addr: %04x!",
__LINE__, __func__, regaddr);
return cnt;
}
return 0;
}
static int idtcm_page_offset(struct idtcm *idtcm, u8 val)
{
u8 buf[4];
int err;
if (idtcm->page_offset == val)
return 0;
buf[0] = 0x0;
buf[1] = val;
buf[2] = 0x10;
buf[3] = 0x20;
err = idtcm_xfer_write(idtcm, PAGE_ADDR, buf, sizeof(buf));
if (err) {
idtcm->page_offset = 0xff;
dev_err(&idtcm->client->dev, "failed to set page offset");
} else {
idtcm->page_offset = val;
}
return err;
}
static int _idtcm_rdwr(struct idtcm *idtcm,
u16 regaddr,
u8 *buf,
u16 count,
bool write)
{
u8 hi;
u8 lo;
int err;
hi = (regaddr >> 8) & 0xff;
lo = regaddr & 0xff;
err = idtcm_page_offset(idtcm, hi);
if (err)
return err;
if (write)
return idtcm_xfer_write(idtcm, lo, buf, count);
return idtcm_xfer_read(idtcm, lo, buf, count);
}
static int idtcm_read(struct idtcm *idtcm,
u16 module,
u16 regaddr,
u8 *buf,
u16 count)
{
return _idtcm_rdwr(idtcm, module + regaddr, buf, count, false);
}
static int idtcm_write(struct idtcm *idtcm,
u16 module,
u16 regaddr,
u8 *buf,
u16 count)
{
return _idtcm_rdwr(idtcm, module + regaddr, buf, count, true);
}
static int clear_boot_status(struct idtcm *idtcm)
{
u8 buf[4] = {0};
......@@ -339,11 +234,82 @@ static int wait_for_boot_status_ready(struct idtcm *idtcm)
} while (i);
dev_warn(&idtcm->client->dev, "%s timed out", __func__);
dev_warn(idtcm->dev, "%s timed out", __func__);
return -EBUSY;
}
static int _idtcm_set_scsr_read_trig(struct idtcm_channel *channel,
enum scsr_read_trig_sel trig, u8 ref)
{
struct idtcm *idtcm = channel->idtcm;
u16 tod_read_cmd = IDTCM_FW_REG(idtcm->fw_ver, V520, TOD_READ_PRIMARY_CMD);
u8 val;
int err;
if (trig == SCSR_TOD_READ_TRIG_SEL_REFCLK) {
err = idtcm_read(idtcm, channel->tod_read_primary,
TOD_READ_PRIMARY_SEL_CFG_0, &val, sizeof(val));
if (err)
return err;
val &= ~(WR_REF_INDEX_MASK << WR_REF_INDEX_SHIFT);
val |= (ref << WR_REF_INDEX_SHIFT);
err = idtcm_write(idtcm, channel->tod_read_primary,
TOD_READ_PRIMARY_SEL_CFG_0, &val, sizeof(val));
if (err)
return err;
}
err = idtcm_read(idtcm, channel->tod_read_primary,
tod_read_cmd, &val, sizeof(val));
if (err)
return err;
val &= ~(TOD_READ_TRIGGER_MASK << TOD_READ_TRIGGER_SHIFT);
val |= (trig << TOD_READ_TRIGGER_SHIFT);
val &= ~TOD_READ_TRIGGER_MODE; /* single shot */
err = idtcm_write(idtcm, channel->tod_read_primary,
tod_read_cmd, &val, sizeof(val));
return err;
}
static int idtcm_enable_extts(struct idtcm_channel *channel, u8 todn, u8 ref,
bool enable)
{
struct idtcm *idtcm = channel->idtcm;
u8 old_mask = idtcm->extts_mask;
u8 mask = 1 << todn;
int err = 0;
if (todn >= MAX_TOD)
return -EINVAL;
if (enable) {
if (ref > 0xF) /* E_REF_CLK15 */
return -EINVAL;
if (idtcm->extts_mask & mask)
return 0;
err = _idtcm_set_scsr_read_trig(&idtcm->channel[todn],
SCSR_TOD_READ_TRIG_SEL_REFCLK,
ref);
if (err == 0) {
idtcm->extts_mask |= mask;
idtcm->event_channel[todn] = channel;
idtcm->channel[todn].refn = ref;
}
} else
idtcm->extts_mask &= ~mask;
if (old_mask == 0 && idtcm->extts_mask)
schedule_delayed_work(&idtcm->extts_work,
msecs_to_jiffies(EXTTS_PERIOD_MS));
return err;
}
static int read_sys_apll_status(struct idtcm *idtcm, u8 *status)
{
return idtcm_read(idtcm, STATUS, DPLL_SYS_APLL_STATUS, status,
......@@ -380,7 +346,7 @@ static int wait_for_sys_apll_dpll_lock(struct idtcm *idtcm)
} else if (dpll == DPLL_STATE_FREERUN ||
dpll == DPLL_STATE_HOLDOVER ||
dpll == DPLL_STATE_OPEN_LOOP) {
dev_warn(&idtcm->client->dev,
dev_warn(idtcm->dev,
"No wait state: DPLL_SYS_STATE %d", dpll);
return -EPERM;
}
......@@ -388,7 +354,7 @@ static int wait_for_sys_apll_dpll_lock(struct idtcm *idtcm)
msleep(LOCK_POLL_INTERVAL_MS);
} while (time_is_after_jiffies(timeout));
dev_warn(&idtcm->client->dev,
dev_warn(idtcm->dev,
"%d ms lock timeout: SYS APLL Loss Lock %d SYS DPLL state %d",
LOCK_TIMEOUT_MS, apll, dpll);
......@@ -398,39 +364,27 @@ static int wait_for_sys_apll_dpll_lock(struct idtcm *idtcm)
static void wait_for_chip_ready(struct idtcm *idtcm)
{
if (wait_for_boot_status_ready(idtcm))
dev_warn(&idtcm->client->dev, "BOOT_STATUS != 0xA0");
dev_warn(idtcm->dev, "BOOT_STATUS != 0xA0");
if (wait_for_sys_apll_dpll_lock(idtcm))
dev_warn(&idtcm->client->dev,
dev_warn(idtcm->dev,
"Continuing while SYS APLL/DPLL is not locked");
}
static int _idtcm_gettime(struct idtcm_channel *channel,
struct timespec64 *ts)
struct timespec64 *ts, u8 timeout)
{
struct idtcm *idtcm = channel->idtcm;
u16 tod_read_cmd = IDTCM_FW_REG(idtcm->fw_ver, V520, TOD_READ_PRIMARY_CMD);
u8 buf[TOD_BYTE_COUNT];
u8 timeout = 10;
u8 trigger;
int err;
err = idtcm_read(idtcm, channel->tod_read_primary,
tod_read_cmd, &trigger, sizeof(trigger));
if (err)
return err;
trigger &= ~(TOD_READ_TRIGGER_MASK << TOD_READ_TRIGGER_SHIFT);
trigger |= (1 << TOD_READ_TRIGGER_SHIFT);
trigger &= ~TOD_READ_TRIGGER_MODE; /* single shot */
err = idtcm_write(idtcm, channel->tod_read_primary,
tod_read_cmd, &trigger, sizeof(trigger));
if (err)
return err;
/* wait trigger to be 0 */
while (trigger & TOD_READ_TRIGGER_MASK) {
do {
if (timeout-- == 0)
return -EIO;
if (idtcm->calculate_overhead_flag)
idtcm->start_time = ktime_get_raw();
......@@ -439,10 +393,7 @@ static int _idtcm_gettime(struct idtcm_channel *channel,
sizeof(trigger));
if (err)
return err;
if (--timeout == 0)
return -EIO;
}
} while (trigger & TOD_READ_TRIGGER_MASK);
err = idtcm_read(idtcm, channel->tod_read_primary,
TOD_READ_PRIMARY, buf, sizeof(buf));
......@@ -454,6 +405,79 @@ static int _idtcm_gettime(struct idtcm_channel *channel,
return err;
}
static int idtcm_extts_check_channel(struct idtcm *idtcm, u8 todn)
{
struct idtcm_channel *ptp_channel, *extts_channel;
struct ptp_clock_event event;
struct timespec64 ts;
u32 dco_delay = 0;
int err;
extts_channel = &idtcm->channel[todn];
ptp_channel = idtcm->event_channel[todn];
if (extts_channel == ptp_channel)
dco_delay = ptp_channel->dco_delay;
err = _idtcm_gettime(extts_channel, &ts, 1);
if (err == 0) {
event.type = PTP_CLOCK_EXTTS;
event.index = todn;
event.timestamp = timespec64_to_ns(&ts) - dco_delay;
ptp_clock_event(ptp_channel->ptp_clock, &event);
}
return err;
}
static u8 idtcm_enable_extts_mask(struct idtcm_channel *channel,
u8 extts_mask, bool enable)
{
struct idtcm *idtcm = channel->idtcm;
int i, err;
for (i = 0; i < MAX_TOD; i++) {
u8 mask = 1 << i;
u8 refn = idtcm->channel[i].refn;
if (extts_mask & mask) {
/* check extts before disabling it */
if (enable == false) {
err = idtcm_extts_check_channel(idtcm, i);
/* trigger happened so we won't re-enable it */
if (err == 0)
extts_mask &= ~mask;
}
(void)idtcm_enable_extts(channel, i, refn, enable);
}
}
return extts_mask;
}
static int _idtcm_gettime_immediate(struct idtcm_channel *channel,
struct timespec64 *ts)
{
struct idtcm *idtcm = channel->idtcm;
u8 extts_mask = 0;
int err;
/* Disable extts */
if (idtcm->extts_mask) {
extts_mask = idtcm_enable_extts_mask(channel, idtcm->extts_mask,
false);
}
err = _idtcm_set_scsr_read_trig(channel,
SCSR_TOD_READ_TRIG_SEL_IMMEDIATE, 0);
if (err == 0)
err = _idtcm_gettime(channel, ts, 10);
/* Re-enable extts */
if (extts_mask)
idtcm_enable_extts_mask(channel, extts_mask, true);
return err;
}
static int _sync_pll_output(struct idtcm *idtcm,
u8 pll,
u8 sync_src,
......@@ -777,7 +801,7 @@ static int _idtcm_set_dpll_scsr_tod(struct idtcm_channel *channel,
break;
if (++count > 20) {
dev_err(&idtcm->client->dev,
dev_err(idtcm->dev,
"Timed out waiting for the write counter");
return -EIO;
}
......@@ -842,7 +866,7 @@ static int _idtcm_settime_deprecated(struct idtcm_channel *channel,
err = _idtcm_set_dpll_hw_tod(channel, ts, HW_TOD_WR_TRIG_SEL_MSB);
if (err) {
dev_err(&idtcm->client->dev,
dev_err(idtcm->dev,
"%s: Set HW ToD failed", __func__);
return err;
}
......@@ -1001,7 +1025,7 @@ static int _idtcm_adjtime_deprecated(struct idtcm_channel *channel, s64 delta)
if (err)
return err;
err = _idtcm_gettime(channel, &ts);
err = _idtcm_gettime_immediate(channel, &ts);
if (err)
return err;
......@@ -1035,14 +1059,14 @@ static int idtcm_state_machine_reset(struct idtcm *idtcm)
read_boot_status(idtcm, &status);
if (status == 0xA0) {
dev_dbg(&idtcm->client->dev,
dev_dbg(idtcm->dev,
"SM_RESET completed in %d ms", i * 100);
break;
}
}
if (!status)
dev_err(&idtcm->client->dev,
dev_err(idtcm->dev,
"Timed out waiting for CM_RESET to complete");
}
......@@ -1139,12 +1163,12 @@ static int set_pll_output_mask(struct idtcm *idtcm, u16 addr, u8 val)
static int set_tod_ptp_pll(struct idtcm *idtcm, u8 index, u8 pll)
{
if (index >= MAX_TOD) {
dev_err(&idtcm->client->dev, "ToD%d not supported", index);
dev_err(idtcm->dev, "ToD%d not supported", index);
return -EINVAL;
}
if (pll >= MAX_PLL) {
dev_err(&idtcm->client->dev, "Pll%d not supported", pll);
dev_err(idtcm->dev, "Pll%d not supported", pll);
return -EINVAL;
}
......@@ -1162,7 +1186,7 @@ static int check_and_set_masks(struct idtcm *idtcm,
switch (regaddr) {
case TOD_MASK_ADDR:
if ((val & 0xf0) || !(val & 0x0f)) {
dev_err(&idtcm->client->dev, "Invalid TOD mask 0x%02x", val);
dev_err(idtcm->dev, "Invalid TOD mask 0x%02x", val);
err = -EINVAL;
} else {
idtcm->tod_mask = val;
......@@ -1193,13 +1217,13 @@ static void display_pll_and_masks(struct idtcm *idtcm)
u8 i;
u8 mask;
dev_dbg(&idtcm->client->dev, "tod_mask = 0x%02x", idtcm->tod_mask);
dev_dbg(idtcm->dev, "tod_mask = 0x%02x", idtcm->tod_mask);
for (i = 0; i < MAX_TOD; i++) {
mask = 1 << i;
if (mask & idtcm->tod_mask)
dev_dbg(&idtcm->client->dev,
dev_dbg(idtcm->dev,
"TOD%d pll = %d output_mask = 0x%04x",
i, idtcm->channel[i].pll,
idtcm->channel[i].output_mask);
......@@ -1222,16 +1246,16 @@ static int idtcm_load_firmware(struct idtcm *idtcm,
if (firmware) /* module parameter */
snprintf(fname, sizeof(fname), "%s", firmware);
dev_info(&idtcm->client->dev, "firmware '%s'", fname);
dev_info(idtcm->dev, "requesting firmware '%s'", fname);
err = request_firmware(&fw, fname, dev);
if (err) {
dev_err(&idtcm->client->dev,
dev_err(idtcm->dev,
"Failed at line %d in %s!", __LINE__, __func__);
return err;
}
dev_dbg(&idtcm->client->dev, "firmware size %zu bytes", fw->size);
dev_dbg(idtcm->dev, "firmware size %zu bytes", fw->size);
rec = (struct idtcm_fwrc *) fw->data;
......@@ -1240,7 +1264,7 @@ static int idtcm_load_firmware(struct idtcm *idtcm,
for (len = fw->size; len > 0; len -= sizeof(*rec)) {
if (rec->reserved) {
dev_err(&idtcm->client->dev,
dev_err(idtcm->dev,
"bad firmware, reserved field non-zero");
err = -EINVAL;
} else {
......@@ -1291,7 +1315,7 @@ static int idtcm_output_enable(struct idtcm_channel *channel,
base = get_output_base_addr(idtcm->fw_ver, outn);
if (!(base > 0)) {
dev_err(&idtcm->client->dev,
dev_err(idtcm->dev,
"%s - Unsupported out%d", __func__, outn);
return base;
}
......@@ -1333,8 +1357,8 @@ static int idtcm_output_mask_enable(struct idtcm_channel *channel,
}
static int idtcm_perout_enable(struct idtcm_channel *channel,
bool enable,
struct ptp_perout_request *perout)
struct ptp_perout_request *perout,
bool enable)
{
struct idtcm *idtcm = channel->idtcm;
unsigned int flags = perout->flags;
......@@ -1347,7 +1371,7 @@ static int idtcm_perout_enable(struct idtcm_channel *channel,
err = idtcm_output_enable(channel, enable, perout->index);
if (err) {
dev_err(&idtcm->client->dev, "Unable to set output enable");
dev_err(idtcm->dev, "Unable to set output enable");
return err;
}
......@@ -1448,7 +1472,7 @@ static int configure_dpll_mode_write_frequency(struct idtcm_channel *channel)
err = idtcm_set_pll_mode(channel, PLL_MODE_WRITE_FREQUENCY);
if (err)
dev_err(&idtcm->client->dev, "Failed to set pll mode to write frequency");
dev_err(idtcm->dev, "Failed to set pll mode to write frequency");
else
channel->mode = PTP_PLL_MODE_WRITE_FREQUENCY;
......@@ -1463,7 +1487,7 @@ static int configure_dpll_mode_write_phase(struct idtcm_channel *channel)
err = idtcm_set_pll_mode(channel, PLL_MODE_WRITE_PHASE);
if (err)
dev_err(&idtcm->client->dev, "Failed to set pll mode to write phase");
dev_err(idtcm->dev, "Failed to set pll mode to write phase");
else
channel->mode = PTP_PLL_MODE_WRITE_PHASE;
......@@ -1478,7 +1502,7 @@ static int configure_manual_reference_write_frequency(struct idtcm_channel *chan
err = idtcm_set_manual_reference(channel, MANU_REF_WRITE_FREQUENCY);
if (err)
dev_err(&idtcm->client->dev, "Failed to set manual reference to write frequency");
dev_err(idtcm->dev, "Failed to set manual reference to write frequency");
else
channel->mode = PTP_PLL_MODE_WRITE_FREQUENCY;
......@@ -1493,7 +1517,7 @@ static int configure_manual_reference_write_phase(struct idtcm_channel *channel)
err = idtcm_set_manual_reference(channel, MANU_REF_WRITE_PHASE);
if (err)
dev_err(&idtcm->client->dev, "Failed to set manual reference to write phase");
dev_err(idtcm->dev, "Failed to set manual reference to write phase");
else
channel->mode = PTP_PLL_MODE_WRITE_PHASE;
......@@ -1518,11 +1542,11 @@ static long idtcm_work_handler(struct ptp_clock_info *ptp)
struct idtcm_channel *channel = container_of(ptp, struct idtcm_channel, caps);
struct idtcm *idtcm = channel->idtcm;
mutex_lock(&idtcm->reg_lock);
mutex_lock(idtcm->lock);
(void)idtcm_stop_phase_pull_in(channel);
mutex_unlock(&idtcm->reg_lock);
mutex_unlock(idtcm->lock);
/* Return a negative value here to not reschedule */
return -1;
......@@ -1533,8 +1557,8 @@ static s32 phase_pull_in_scaled_ppm(s32 current_ppm, s32 phase_pull_in_ppb)
/* ppb = scaled_ppm * 125 / 2^13 */
/* scaled_ppm = ppb * 2^13 / 125 */
s64 max_scaled_ppm = (PHASE_PULL_IN_MAX_PPB << 13) / 125;
s64 scaled_ppm = (phase_pull_in_ppb << 13) / 125;
s64 max_scaled_ppm = div_s64((s64)PHASE_PULL_IN_MAX_PPB << 13, 125);
s64 scaled_ppm = div_s64((s64)phase_pull_in_ppb << 13, 125);
current_ppm += scaled_ppm;
......@@ -1607,7 +1631,7 @@ static int initialize_operating_mode_with_manual_reference(struct idtcm_channel
channel->mode = PTP_PLL_MODE_WRITE_FREQUENCY;
break;
default:
dev_warn(&idtcm->client->dev,
dev_warn(idtcm->dev,
"Unsupported MANUAL_REFERENCE: 0x%02x", ref);
}
......@@ -1633,7 +1657,7 @@ static int initialize_operating_mode_with_pll_mode(struct idtcm_channel *channel
channel->mode = PTP_PLL_MODE_WRITE_FREQUENCY;
break;
default:
dev_err(&idtcm->client->dev,
dev_err(idtcm->dev,
"Unsupported PLL_MODE: 0x%02x", mode);
err = -EINVAL;
}
......@@ -1652,14 +1676,14 @@ static int initialize_dco_operating_mode(struct idtcm_channel *channel)
err = idtcm_get_pll_mode(channel, &mode);
if (err) {
dev_err(&idtcm->client->dev, "Unable to read pll mode!");
dev_err(idtcm->dev, "Unable to read pll mode!");
return err;
}
if (mode == PLL_MODE_PLL) {
err = idtcm_get_manual_reference(channel, &ref);
if (err) {
dev_err(&idtcm->client->dev, "Unable to read manual reference!");
dev_err(idtcm->dev, "Unable to read manual reference!");
return err;
}
err = initialize_operating_mode_with_manual_reference(channel, ref);
......@@ -1775,15 +1799,14 @@ static int idtcm_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts)
struct idtcm *idtcm = channel->idtcm;
int err;
mutex_lock(&idtcm->reg_lock);
mutex_lock(idtcm->lock);
err = _idtcm_gettime_immediate(channel, ts);
mutex_unlock(idtcm->lock);
err = _idtcm_gettime(channel, ts);
if (err)
dev_err(&idtcm->client->dev, "Failed at line %d in %s!",
dev_err(idtcm->dev, "Failed at line %d in %s!",
__LINE__, __func__);
mutex_unlock(&idtcm->reg_lock);
return err;
}
......@@ -1794,15 +1817,14 @@ static int idtcm_settime_deprecated(struct ptp_clock_info *ptp,
struct idtcm *idtcm = channel->idtcm;
int err;
mutex_lock(&idtcm->reg_lock);
mutex_lock(idtcm->lock);
err = _idtcm_settime_deprecated(channel, ts);
mutex_unlock(idtcm->lock);
if (err)
dev_err(&idtcm->client->dev,
dev_err(idtcm->dev,
"Failed at line %d in %s!", __LINE__, __func__);
mutex_unlock(&idtcm->reg_lock);
return err;
}
......@@ -1813,15 +1835,14 @@ static int idtcm_settime(struct ptp_clock_info *ptp,
struct idtcm *idtcm = channel->idtcm;
int err;
mutex_lock(&idtcm->reg_lock);
mutex_lock(idtcm->lock);
err = _idtcm_settime(channel, ts, SCSR_TOD_WR_TYPE_SEL_ABSOLUTE);
mutex_unlock(idtcm->lock);
if (err)
dev_err(&idtcm->client->dev,
dev_err(idtcm->dev,
"Failed at line %d in %s!", __LINE__, __func__);
mutex_unlock(&idtcm->reg_lock);
return err;
}
......@@ -1831,15 +1852,14 @@ static int idtcm_adjtime_deprecated(struct ptp_clock_info *ptp, s64 delta)
struct idtcm *idtcm = channel->idtcm;
int err;
mutex_lock(&idtcm->reg_lock);
mutex_lock(idtcm->lock);
err = _idtcm_adjtime_deprecated(channel, delta);
mutex_unlock(idtcm->lock);
if (err)
dev_err(&idtcm->client->dev,
dev_err(idtcm->dev,
"Failed at line %d in %s!", __LINE__, __func__);
mutex_unlock(&idtcm->reg_lock);
return err;
}
......@@ -1854,13 +1874,10 @@ static int idtcm_adjtime(struct ptp_clock_info *ptp, s64 delta)
if (channel->phase_pull_in == true)
return 0;
mutex_lock(&idtcm->reg_lock);
mutex_lock(idtcm->lock);
if (abs(delta) < PHASE_PULL_IN_THRESHOLD_NS) {
err = channel->do_phase_pull_in(channel, delta, 0);
if (err)
dev_err(&idtcm->client->dev,
"Failed at line %d in %s!", __LINE__, __func__);
} else {
if (delta >= 0) {
ts = ns_to_timespec64(delta);
......@@ -1870,11 +1887,13 @@ static int idtcm_adjtime(struct ptp_clock_info *ptp, s64 delta)
type = SCSR_TOD_WR_TYPE_SEL_DELTA_MINUS;
}
err = _idtcm_settime(channel, &ts, type);
if (err)
dev_err(&idtcm->client->dev,
"Failed at line %d in %s!", __LINE__, __func__);
}
mutex_unlock(&idtcm->reg_lock);
mutex_unlock(idtcm->lock);
if (err)
dev_err(idtcm->dev,
"Failed at line %d in %s!", __LINE__, __func__);
return err;
}
......@@ -1885,15 +1904,14 @@ static int idtcm_adjphase(struct ptp_clock_info *ptp, s32 delta)
struct idtcm *idtcm = channel->idtcm;
int err;
mutex_lock(&idtcm->reg_lock);
mutex_lock(idtcm->lock);
err = _idtcm_adjphase(channel, delta);
mutex_unlock(idtcm->lock);
if (err)
dev_err(&idtcm->client->dev,
dev_err(idtcm->dev,
"Failed at line %d in %s!", __LINE__, __func__);
mutex_unlock(&idtcm->reg_lock);
return err;
}
......@@ -1909,13 +1927,14 @@ static int idtcm_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
if (scaled_ppm == channel->current_freq_scaled_ppm)
return 0;
mutex_lock(&idtcm->reg_lock);
mutex_lock(idtcm->lock);
err = _idtcm_adjfine(channel, scaled_ppm);
mutex_unlock(idtcm->lock);
mutex_unlock(&idtcm->reg_lock);
if (!err)
if (err)
dev_err(idtcm->dev,
"Failed at line %d in %s!", __LINE__, __func__);
else
channel->current_freq_scaled_ppm = scaled_ppm;
return err;
......@@ -1924,35 +1943,38 @@ static int idtcm_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
static int idtcm_enable(struct ptp_clock_info *ptp,
struct ptp_clock_request *rq, int on)
{
int err;
struct idtcm_channel *channel = container_of(ptp, struct idtcm_channel, caps);
struct idtcm *idtcm = channel->idtcm;
int err = -EOPNOTSUPP;
mutex_lock(idtcm->lock);
switch (rq->type) {
case PTP_CLK_REQ_PEROUT:
if (!on) {
err = idtcm_perout_enable(channel, false, &rq->perout);
if (err)
dev_err(&channel->idtcm->client->dev,
"Failed at line %d in %s!",
__LINE__, __func__);
return err;
}
if (!on)
err = idtcm_perout_enable(channel, &rq->perout, false);
/* Only accept a 1-PPS aligned to the second. */
if (rq->perout.start.nsec || rq->perout.period.sec != 1 ||
rq->perout.period.nsec)
return -ERANGE;
err = idtcm_perout_enable(channel, true, &rq->perout);
if (err)
dev_err(&channel->idtcm->client->dev,
"Failed at line %d in %s!", __LINE__, __func__);
return err;
else if (rq->perout.start.nsec || rq->perout.period.sec != 1 ||
rq->perout.period.nsec)
err = -ERANGE;
else
err = idtcm_perout_enable(channel, &rq->perout, true);
break;
case PTP_CLK_REQ_EXTTS:
err = idtcm_enable_extts(channel, rq->extts.index,
rq->extts.rsv[0], on);
break;
default:
break;
}
return -EOPNOTSUPP;
mutex_unlock(idtcm->lock);
if (err)
dev_err(channel->idtcm->dev,
"Failed in %s with err %d!", __func__, err);
return err;
}
static int idtcm_enable_tod(struct idtcm_channel *channel)
......@@ -2013,7 +2035,7 @@ static void idtcm_set_version_info(struct idtcm *idtcm)
idtcm->fw_ver = idtcm_fw_version(idtcm->version);
dev_info(&idtcm->client->dev,
dev_info(idtcm->dev,
"%d.%d.%d, Id: 0x%04x HW Rev: %d OTP Config Select: %d",
major, minor, hotfix,
product_id, hw_rev_id, config_select);
......@@ -2023,6 +2045,7 @@ static const struct ptp_clock_info idtcm_caps = {
.owner = THIS_MODULE,
.max_adj = 244000,
.n_per_out = 12,
.n_ext_ts = MAX_TOD,
.adjphase = &idtcm_adjphase,
.adjfine = &idtcm_adjfine,
.adjtime = &idtcm_adjtime,
......@@ -2036,6 +2059,7 @@ static const struct ptp_clock_info idtcm_caps_deprecated = {
.owner = THIS_MODULE,
.max_adj = 244000,
.n_per_out = 12,
.n_ext_ts = MAX_TOD,
.adjphase = &idtcm_adjphase,
.adjfine = &idtcm_adjfine,
.adjtime = &idtcm_adjtime_deprecated,
......@@ -2122,24 +2146,46 @@ static int configure_channel_pll(struct idtcm_channel *channel)
return err;
}
static int idtcm_enable_channel(struct idtcm *idtcm, u32 index)
/*
* Compensate for the PTP DCO input-to-output delay.
* This delay is 18 FOD cycles.
*/
static u32 idtcm_get_dco_delay(struct idtcm_channel *channel)
{
enum fw_version fw_ver = idtcm->fw_ver;
struct idtcm_channel *channel;
struct idtcm *idtcm = channel->idtcm;
u8 mbuf[8] = {0};
u8 nbuf[2] = {0};
u32 fodFreq;
int err;
u64 m;
u16 n;
if (!(index < MAX_TOD))
return -EINVAL;
err = idtcm_read(idtcm, channel->dpll_ctrl_n,
DPLL_CTRL_DPLL_FOD_FREQ, mbuf, 6);
if (err)
return 0;
channel = &idtcm->channel[index];
err = idtcm_read(idtcm, channel->dpll_ctrl_n,
DPLL_CTRL_DPLL_FOD_FREQ + 6, nbuf, 2);
if (err)
return 0;
channel->idtcm = idtcm;
channel->current_freq_scaled_ppm = 0;
m = get_unaligned_le64(mbuf);
n = get_unaligned_le16(nbuf);
/* Set pll addresses */
err = configure_channel_pll(channel);
if (err)
return err;
if (n == 0)
n = 1;
fodFreq = (u32)div_u64(m, n);
if (fodFreq >= 500000000)
return 18 * (u32)div_u64(NSEC_PER_SEC, fodFreq);
return 0;
}
static int configure_channel_tod(struct idtcm_channel *channel, u32 index)
{
enum fw_version fw_ver = channel->idtcm->fw_ver;
/* Set tod addresses */
switch (index) {
......@@ -2171,6 +2217,32 @@ static int idtcm_enable_channel(struct idtcm *idtcm, u32 index)
return -EINVAL;
}
return 0;
}
static int idtcm_enable_channel(struct idtcm *idtcm, u32 index)
{
struct idtcm_channel *channel;
int err;
if (!(index < MAX_TOD))
return -EINVAL;
channel = &idtcm->channel[index];
channel->idtcm = idtcm;
channel->current_freq_scaled_ppm = 0;
/* Set pll addresses */
err = configure_channel_pll(channel);
if (err)
return err;
/* Set tod addresses */
err = configure_channel_tod(channel, index);
if (err)
return err;
if (idtcm->fw_ver < V487)
channel->caps = idtcm_caps_deprecated;
else
......@@ -2185,11 +2257,13 @@ static int idtcm_enable_channel(struct idtcm *idtcm, u32 index)
err = idtcm_enable_tod(channel);
if (err) {
dev_err(&idtcm->client->dev,
dev_err(idtcm->dev,
"Failed at line %d in %s!", __LINE__, __func__);
return err;
}
channel->dco_delay = idtcm_get_dco_delay(channel);
channel->ptp_clock = ptp_clock_register(&channel->caps, NULL);
if (IS_ERR(channel->ptp_clock)) {
......@@ -2201,12 +2275,59 @@ static int idtcm_enable_channel(struct idtcm *idtcm, u32 index)
if (!channel->ptp_clock)
return -ENOTSUPP;
dev_info(&idtcm->client->dev, "PLL%d registered as ptp%d",
dev_info(idtcm->dev, "PLL%d registered as ptp%d",
index, channel->ptp_clock->index);
return 0;
}
static int idtcm_enable_extts_channel(struct idtcm *idtcm, u32 index)
{
struct idtcm_channel *channel;
int err;
if (!(index < MAX_TOD))
return -EINVAL;
channel = &idtcm->channel[index];
channel->idtcm = idtcm;
/* Set tod addresses */
err = configure_channel_tod(channel, index);
if (err)
return err;
channel->idtcm = idtcm;
return 0;
}
static void idtcm_extts_check(struct work_struct *work)
{
struct idtcm *idtcm = container_of(work, struct idtcm, extts_work.work);
int err, i;
if (idtcm->extts_mask == 0)
return;
mutex_lock(idtcm->lock);
for (i = 0; i < MAX_TOD; i++) {
u8 mask = 1 << i;
if (idtcm->extts_mask & mask) {
err = idtcm_extts_check_channel(idtcm, i);
/* trigger clears itself, so clear the mask */
if (err == 0)
idtcm->extts_mask &= ~mask;
}
}
if (idtcm->extts_mask)
schedule_delayed_work(&idtcm->extts_work,
msecs_to_jiffies(EXTTS_PERIOD_MS));
mutex_unlock(idtcm->lock);
}
static void ptp_clock_unregister_all(struct idtcm *idtcm)
{
u8 i;
......@@ -2222,6 +2343,7 @@ static void ptp_clock_unregister_all(struct idtcm *idtcm)
static void set_default_masks(struct idtcm *idtcm)
{
idtcm->tod_mask = DEFAULT_TOD_MASK;
idtcm->extts_mask = 0;
idtcm->channel[0].pll = DEFAULT_TOD0_PTP_PLL;
idtcm->channel[1].pll = DEFAULT_TOD1_PTP_PLL;
......@@ -2234,158 +2356,86 @@ static void set_default_masks(struct idtcm *idtcm)
idtcm->channel[3].output_mask = DEFAULT_OUTPUT_MASK_PLL3;
}
static int idtcm_probe(struct i2c_client *client,
const struct i2c_device_id *id)
static int idtcm_probe(struct platform_device *pdev)
{
struct rsmu_ddata *ddata = dev_get_drvdata(pdev->dev.parent);
struct idtcm *idtcm;
int err;
u8 i;
/* Unused for now */
(void)id;
idtcm = devm_kzalloc(&client->dev, sizeof(struct idtcm), GFP_KERNEL);
idtcm = devm_kzalloc(&pdev->dev, sizeof(struct idtcm), GFP_KERNEL);
if (!idtcm)
return -ENOMEM;
idtcm->client = client;
idtcm->page_offset = 0xff;
idtcm->dev = &pdev->dev;
idtcm->mfd = pdev->dev.parent;
idtcm->lock = &ddata->lock;
idtcm->regmap = ddata->regmap;
idtcm->calculate_overhead_flag = 0;
INIT_DELAYED_WORK(&idtcm->extts_work, idtcm_extts_check);
set_default_masks(idtcm);
mutex_init(&idtcm->reg_lock);
mutex_lock(&idtcm->reg_lock);
mutex_lock(idtcm->lock);
idtcm_set_version_info(idtcm);
err = idtcm_load_firmware(idtcm, &client->dev);
err = idtcm_load_firmware(idtcm, &pdev->dev);
if (err)
dev_warn(&idtcm->client->dev, "loading firmware failed with %d", err);
dev_warn(idtcm->dev, "loading firmware failed with %d", err);
wait_for_chip_ready(idtcm);
if (idtcm->tod_mask) {
for (i = 0; i < MAX_TOD; i++) {
if (idtcm->tod_mask & (1 << i)) {
if (idtcm->tod_mask & (1 << i))
err = idtcm_enable_channel(idtcm, i);
if (err) {
dev_err(&idtcm->client->dev,
"idtcm_enable_channel %d failed!", i);
break;
}
else
err = idtcm_enable_extts_channel(idtcm, i);
if (err) {
dev_err(idtcm->dev,
"idtcm_enable_channel %d failed!", i);
break;
}
}
} else {
dev_err(&idtcm->client->dev,
dev_err(idtcm->dev,
"no PLLs flagged as PHCs, nothing to do");
err = -ENODEV;
}
mutex_unlock(&idtcm->reg_lock);
mutex_unlock(idtcm->lock);
if (err) {
ptp_clock_unregister_all(idtcm);
return err;
}
i2c_set_clientdata(client, idtcm);
platform_set_drvdata(pdev, idtcm);
return 0;
}
static int idtcm_remove(struct i2c_client *client)
static int idtcm_remove(struct platform_device *pdev)
{
struct idtcm *idtcm = i2c_get_clientdata(client);
struct idtcm *idtcm = platform_get_drvdata(pdev);
ptp_clock_unregister_all(idtcm);
mutex_destroy(&idtcm->reg_lock);
cancel_delayed_work_sync(&idtcm->extts_work);
return 0;
}
#ifdef CONFIG_OF
static const struct of_device_id idtcm_dt_id[] = {
{ .compatible = "idt,8a34000" },
{ .compatible = "idt,8a34001" },
{ .compatible = "idt,8a34002" },
{ .compatible = "idt,8a34003" },
{ .compatible = "idt,8a34004" },
{ .compatible = "idt,8a34005" },
{ .compatible = "idt,8a34006" },
{ .compatible = "idt,8a34007" },
{ .compatible = "idt,8a34008" },
{ .compatible = "idt,8a34009" },
{ .compatible = "idt,8a34010" },
{ .compatible = "idt,8a34011" },
{ .compatible = "idt,8a34012" },
{ .compatible = "idt,8a34013" },
{ .compatible = "idt,8a34014" },
{ .compatible = "idt,8a34015" },
{ .compatible = "idt,8a34016" },
{ .compatible = "idt,8a34017" },
{ .compatible = "idt,8a34018" },
{ .compatible = "idt,8a34019" },
{ .compatible = "idt,8a34040" },
{ .compatible = "idt,8a34041" },
{ .compatible = "idt,8a34042" },
{ .compatible = "idt,8a34043" },
{ .compatible = "idt,8a34044" },
{ .compatible = "idt,8a34045" },
{ .compatible = "idt,8a34046" },
{ .compatible = "idt,8a34047" },
{ .compatible = "idt,8a34048" },
{ .compatible = "idt,8a34049" },
{},
};
MODULE_DEVICE_TABLE(of, idtcm_dt_id);
#endif
static const struct i2c_device_id idtcm_i2c_id[] = {
{ "8a34000" },
{ "8a34001" },
{ "8a34002" },
{ "8a34003" },
{ "8a34004" },
{ "8a34005" },
{ "8a34006" },
{ "8a34007" },
{ "8a34008" },
{ "8a34009" },
{ "8a34010" },
{ "8a34011" },
{ "8a34012" },
{ "8a34013" },
{ "8a34014" },
{ "8a34015" },
{ "8a34016" },
{ "8a34017" },
{ "8a34018" },
{ "8a34019" },
{ "8a34040" },
{ "8a34041" },
{ "8a34042" },
{ "8a34043" },
{ "8a34044" },
{ "8a34045" },
{ "8a34046" },
{ "8a34047" },
{ "8a34048" },
{ "8a34049" },
{},
};
MODULE_DEVICE_TABLE(i2c, idtcm_i2c_id);
static struct i2c_driver idtcm_driver = {
static struct platform_driver idtcm_driver = {
.driver = {
.of_match_table = of_match_ptr(idtcm_dt_id),
.name = "idtcm",
.name = "8a3400x-phc",
},
.probe = idtcm_probe,
.remove = idtcm_remove,
.id_table = idtcm_i2c_id,
.probe = idtcm_probe,
.remove = idtcm_remove,
};
module_i2c_driver(idtcm_driver);
module_platform_driver(idtcm_driver);
......@@ -9,8 +9,8 @@
#define PTP_IDTCLOCKMATRIX_H
#include <linux/ktime.h>
#include "idt8a340_reg.h"
#include <linux/mfd/idt8a340_reg.h>
#include <linux/regmap.h>
#define FW_FILENAME "idtcm.bin"
#define MAX_TOD (4)
......@@ -44,7 +44,6 @@
#define DEFAULT_TOD2_PTP_PLL (2)
#define DEFAULT_TOD3_PTP_PLL (3)
#define POST_SM_RESET_DELAY_MS (3000)
#define PHASE_PULL_IN_THRESHOLD_NS_DEPRECATED (150000)
#define PHASE_PULL_IN_THRESHOLD_NS (15000)
#define TOD_WRITE_OVERHEAD_COUNT_MAX (2)
......@@ -64,6 +63,11 @@
* Return register address based on passed in firmware version
*/
#define IDTCM_FW_REG(FW, VER, REG) (((FW) < (VER)) ? (REG) : (REG##_##VER))
enum fw_version {
V_DEFAULT = 0,
V487 = 1,
V520 = 2,
};
/* PTP PLL Mode */
enum ptp_pll_mode {
......@@ -74,94 +78,6 @@ enum ptp_pll_mode {
PTP_PLL_MODE_MAX = PTP_PLL_MODE_UNSUPPORTED,
};
/* Values of DPLL_N.DPLL_MODE.PLL_MODE */
enum pll_mode {
PLL_MODE_MIN = 0,
PLL_MODE_PLL = PLL_MODE_MIN,
PLL_MODE_WRITE_PHASE = 1,
PLL_MODE_WRITE_FREQUENCY = 2,
PLL_MODE_GPIO_INC_DEC = 3,
PLL_MODE_SYNTHESIS = 4,
PLL_MODE_PHASE_MEASUREMENT = 5,
PLL_MODE_DISABLED = 6,
PLL_MODE_MAX = PLL_MODE_DISABLED,
};
/* Values of DPLL_CTRL_n.DPLL_MANU_REF_CFG.MANUAL_REFERENCE */
enum manual_reference {
MANU_REF_MIN = 0,
MANU_REF_CLK0 = MANU_REF_MIN,
MANU_REF_CLK1,
MANU_REF_CLK2,
MANU_REF_CLK3,
MANU_REF_CLK4,
MANU_REF_CLK5,
MANU_REF_CLK6,
MANU_REF_CLK7,
MANU_REF_CLK8,
MANU_REF_CLK9,
MANU_REF_CLK10,
MANU_REF_CLK11,
MANU_REF_CLK12,
MANU_REF_CLK13,
MANU_REF_CLK14,
MANU_REF_CLK15,
MANU_REF_WRITE_PHASE,
MANU_REF_WRITE_FREQUENCY,
MANU_REF_XO_DPLL,
MANU_REF_MAX = MANU_REF_XO_DPLL,
};
enum hw_tod_write_trig_sel {
HW_TOD_WR_TRIG_SEL_MIN = 0,
HW_TOD_WR_TRIG_SEL_MSB = HW_TOD_WR_TRIG_SEL_MIN,
HW_TOD_WR_TRIG_SEL_RESERVED = 1,
HW_TOD_WR_TRIG_SEL_TOD_PPS = 2,
HW_TOD_WR_TRIG_SEL_IRIGB_PPS = 3,
HW_TOD_WR_TRIG_SEL_PWM_PPS = 4,
HW_TOD_WR_TRIG_SEL_GPIO = 5,
HW_TOD_WR_TRIG_SEL_FOD_SYNC = 6,
WR_TRIG_SEL_MAX = HW_TOD_WR_TRIG_SEL_FOD_SYNC,
};
/* 4.8.7 only */
enum scsr_tod_write_trig_sel {
SCSR_TOD_WR_TRIG_SEL_DISABLE = 0,
SCSR_TOD_WR_TRIG_SEL_IMMEDIATE = 1,
SCSR_TOD_WR_TRIG_SEL_REFCLK = 2,
SCSR_TOD_WR_TRIG_SEL_PWMPPS = 3,
SCSR_TOD_WR_TRIG_SEL_TODPPS = 4,
SCSR_TOD_WR_TRIG_SEL_SYNCFOD = 5,
SCSR_TOD_WR_TRIG_SEL_GPIO = 6,
SCSR_TOD_WR_TRIG_SEL_MAX = SCSR_TOD_WR_TRIG_SEL_GPIO,
};
/* 4.8.7 only */
enum scsr_tod_write_type_sel {
SCSR_TOD_WR_TYPE_SEL_ABSOLUTE = 0,
SCSR_TOD_WR_TYPE_SEL_DELTA_PLUS = 1,
SCSR_TOD_WR_TYPE_SEL_DELTA_MINUS = 2,
SCSR_TOD_WR_TYPE_SEL_MAX = SCSR_TOD_WR_TYPE_SEL_DELTA_MINUS,
};
/* Values STATUS.DPLL_SYS_STATUS.DPLL_SYS_STATE */
enum dpll_state {
DPLL_STATE_MIN = 0,
DPLL_STATE_FREERUN = DPLL_STATE_MIN,
DPLL_STATE_LOCKACQ = 1,
DPLL_STATE_LOCKREC = 2,
DPLL_STATE_LOCKED = 3,
DPLL_STATE_HOLDOVER = 4,
DPLL_STATE_OPEN_LOOP = 5,
DPLL_STATE_MAX = DPLL_STATE_OPEN_LOOP,
};
enum fw_version {
V_DEFAULT = 0,
V487 = 1,
V520 = 2,
};
struct idtcm;
struct idtcm_channel {
......@@ -185,25 +101,32 @@ struct idtcm_channel {
s32 offset_ns, u32 max_ffo_ppb);
s32 current_freq_scaled_ppm;
bool phase_pull_in;
u32 dco_delay;
/* last input trigger for extts */
u8 refn;
u8 pll;
u16 output_mask;
};
struct idtcm {
struct idtcm_channel channel[MAX_TOD];
struct i2c_client *client;
u8 page_offset;
struct device *dev;
u8 tod_mask;
char version[16];
enum fw_version fw_ver;
/* Polls for external time stamps */
u8 extts_mask;
struct delayed_work extts_work;
/* Remember the ptp channel to report extts */
struct idtcm_channel *event_channel[MAX_TOD];
/* Mutex to protect operations from being interrupted */
struct mutex *lock;
struct device *mfd;
struct regmap *regmap;
/* Overhead calculation for adjtime */
u8 calculate_overhead_flag;
s64 tod_write_overhead_ns;
ktime_t start_time;
/* Protects I2C read/modify/write registers from concurrent access */
struct mutex reg_lock;
};
struct idtcm_fwrc {
......
......@@ -506,6 +506,10 @@
#define STATE_MODE_SHIFT (0)
#define STATE_MODE_MASK (0x7)
/* Bit definitions for the DPLL_MANU_REF_CFG register */
#define MANUAL_REFERENCE_SHIFT (0)
#define MANUAL_REFERENCE_MASK (0x1f)
/* Bit definitions for the GPIO_CFG_GBL register */
#define SUPPLY_MODE_SHIFT (0)
#define SUPPLY_MODE_MASK (0x3)
......@@ -654,7 +658,7 @@
/* Values of DPLL_N.DPLL_MODE.PLL_MODE */
enum pll_mode {
PLL_MODE_MIN = 0,
PLL_MODE_NORMAL = PLL_MODE_MIN,
PLL_MODE_PLL = PLL_MODE_MIN,
PLL_MODE_WRITE_PHASE = 1,
PLL_MODE_WRITE_FREQUENCY = 2,
PLL_MODE_GPIO_INC_DEC = 3,
......@@ -664,6 +668,31 @@ enum pll_mode {
PLL_MODE_MAX = PLL_MODE_DISABLED,
};
/* Values of DPLL_CTRL_n.DPLL_MANU_REF_CFG.MANUAL_REFERENCE */
enum manual_reference {
MANU_REF_MIN = 0,
MANU_REF_CLK0 = MANU_REF_MIN,
MANU_REF_CLK1,
MANU_REF_CLK2,
MANU_REF_CLK3,
MANU_REF_CLK4,
MANU_REF_CLK5,
MANU_REF_CLK6,
MANU_REF_CLK7,
MANU_REF_CLK8,
MANU_REF_CLK9,
MANU_REF_CLK10,
MANU_REF_CLK11,
MANU_REF_CLK12,
MANU_REF_CLK13,
MANU_REF_CLK14,
MANU_REF_CLK15,
MANU_REF_WRITE_PHASE,
MANU_REF_WRITE_FREQUENCY,
MANU_REF_XO_DPLL,
MANU_REF_MAX = MANU_REF_XO_DPLL,
};
enum hw_tod_write_trig_sel {
HW_TOD_WR_TRIG_SEL_MIN = 0,
HW_TOD_WR_TRIG_SEL_MSB = HW_TOD_WR_TRIG_SEL_MIN,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment