1313#include <linux/init.h>
1414#include <linux/module.h>
1515#include <linux/kernel.h>
16+ #include <linux/regmap.h>
1617#include <linux/interrupt.h>
18+ #include <linux/mfd/syscon.h>
1719#include <linux/mod_devicetable.h>
1820#include <linux/platform_device.h>
1921#include <linux/mailbox_controller.h>
2022#include <soc/microchip/mpfs.h>
2123
24+ #define MESSAGE_INT_OFFSET 0x18cu
2225#define SERVICES_CR_OFFSET 0x50u
2326#define SERVICES_SR_OFFSET 0x54u
2427#define MAILBOX_REG_OFFSET 0x800u
@@ -68,14 +71,18 @@ struct mpfs_mbox {
6871 void __iomem * int_reg ;
6972 struct mbox_chan chans [1 ];
7073 struct mpfs_mss_response * response ;
74+ struct regmap * sysreg_scb , * control_scb ;
7175 u16 resp_offset ;
7276};
7377
7478static bool mpfs_mbox_busy (struct mpfs_mbox * mbox )
7579{
7680 u32 status ;
7781
78- status = readl_relaxed (mbox -> ctrl_base + SERVICES_SR_OFFSET );
82+ if (mbox -> control_scb )
83+ regmap_read (mbox -> control_scb , SERVICES_SR_OFFSET , & status );
84+ else
85+ status = readl_relaxed (mbox -> ctrl_base + SERVICES_SR_OFFSET );
7986
8087 return status & SCB_STATUS_BUSY_MASK ;
8188}
@@ -95,7 +102,11 @@ static bool mpfs_mbox_last_tx_done(struct mbox_chan *chan)
95102 * Failed services are intended to generated interrupts, but in reality
96103 * this does not happen, so the status must be checked here.
97104 */
98- val = readl_relaxed (mbox -> ctrl_base + SERVICES_SR_OFFSET );
105+ if (mbox -> control_scb )
106+ regmap_read (mbox -> control_scb , SERVICES_SR_OFFSET , & val );
107+ else
108+ val = readl_relaxed (mbox -> ctrl_base + SERVICES_SR_OFFSET );
109+
99110 response -> resp_status = (val & SCB_STATUS_MASK ) >> SCB_STATUS_POS ;
100111
101112 return true;
@@ -143,7 +154,12 @@ static int mpfs_mbox_send_data(struct mbox_chan *chan, void *data)
143154
144155 tx_trigger = (opt_sel << SCB_CTRL_POS ) & SCB_CTRL_MASK ;
145156 tx_trigger |= SCB_CTRL_REQ_MASK | SCB_STATUS_NOTIFY_MASK ;
146- writel_relaxed (tx_trigger , mbox -> ctrl_base + SERVICES_CR_OFFSET );
157+
158+ if (mbox -> control_scb )
159+ regmap_write (mbox -> control_scb , SERVICES_CR_OFFSET , tx_trigger );
160+ else
161+ writel_relaxed (tx_trigger , mbox -> ctrl_base + SERVICES_CR_OFFSET );
162+
147163
148164 return 0 ;
149165}
@@ -185,7 +201,10 @@ static irqreturn_t mpfs_mbox_inbox_isr(int irq, void *data)
185201 struct mbox_chan * chan = data ;
186202 struct mpfs_mbox * mbox = (struct mpfs_mbox * )chan -> con_priv ;
187203
188- writel_relaxed (0 , mbox -> int_reg );
204+ if (mbox -> control_scb )
205+ regmap_write (mbox -> sysreg_scb , MESSAGE_INT_OFFSET , 0 );
206+ else
207+ writel_relaxed (0 , mbox -> int_reg );
189208
190209 mpfs_mbox_rx_data (chan );
191210
@@ -221,28 +240,62 @@ static const struct mbox_chan_ops mpfs_mbox_ops = {
221240 .last_tx_done = mpfs_mbox_last_tx_done ,
222241};
223242
224- static int mpfs_mbox_probe ( struct platform_device * pdev )
243+ static inline int mpfs_mbox_syscon_probe ( struct mpfs_mbox * mbox , struct platform_device * pdev )
225244{
226- struct mpfs_mbox * mbox ;
227- struct resource * regs ;
228- int ret ;
245+ mbox -> control_scb = syscon_regmap_lookup_by_compatible ( "microchip,mpfs-control-scb" ) ;
246+ if ( IS_ERR ( mbox -> control_scb ))
247+ return PTR_ERR ( mbox -> control_scb ) ;
229248
230- mbox = devm_kzalloc (& pdev -> dev , sizeof (* mbox ), GFP_KERNEL );
231- if (!mbox )
232- return - ENOMEM ;
249+ mbox -> sysreg_scb = syscon_regmap_lookup_by_compatible ("microchip,mpfs-sysreg-scb" );
250+ if (IS_ERR (mbox -> sysreg_scb ))
251+ return PTR_ERR (mbox -> sysreg_scb );
252+
253+ mbox -> mbox_base = devm_platform_ioremap_resource (pdev , 0 );
254+ if (IS_ERR (mbox -> ctrl_base ))
255+ return PTR_ERR (mbox -> mbox_base );
256+
257+ return 0 ;
258+ }
259+
260+ static inline int mpfs_mbox_old_format_probe (struct mpfs_mbox * mbox , struct platform_device * pdev )
261+ {
262+ dev_warn (& pdev -> dev , "falling back to old devicetree format" );
233263
234- mbox -> ctrl_base = devm_platform_get_and_ioremap_resource (pdev , 0 , & regs );
264+ mbox -> ctrl_base = devm_platform_ioremap_resource (pdev , 0 );
235265 if (IS_ERR (mbox -> ctrl_base ))
236266 return PTR_ERR (mbox -> ctrl_base );
237267
238- mbox -> int_reg = devm_platform_get_and_ioremap_resource (pdev , 1 , & regs );
268+ mbox -> int_reg = devm_platform_ioremap_resource (pdev , 1 );
239269 if (IS_ERR (mbox -> int_reg ))
240270 return PTR_ERR (mbox -> int_reg );
241271
242- mbox -> mbox_base = devm_platform_get_and_ioremap_resource (pdev , 2 , & regs );
272+ mbox -> mbox_base = devm_platform_ioremap_resource (pdev , 2 );
243273 if (IS_ERR (mbox -> mbox_base )) // account for the old dt-binding w/ 2 regs
244274 mbox -> mbox_base = mbox -> ctrl_base + MAILBOX_REG_OFFSET ;
245275
276+ return 0 ;
277+ }
278+
279+ static int mpfs_mbox_probe (struct platform_device * pdev )
280+ {
281+ struct mpfs_mbox * mbox ;
282+ int ret ;
283+
284+ mbox = devm_kzalloc (& pdev -> dev , sizeof (* mbox ), GFP_KERNEL );
285+ if (!mbox )
286+ return - ENOMEM ;
287+
288+ ret = mpfs_mbox_syscon_probe (mbox , pdev );
289+ if (ret ) {
290+ /*
291+ * set this to null, so it can be used as the decision for to
292+ * regmap or not to regmap
293+ */
294+ mbox -> control_scb = NULL ;
295+ ret = mpfs_mbox_old_format_probe (mbox , pdev );
296+ if (ret )
297+ return ret ;
298+ }
246299 mbox -> irq = platform_get_irq (pdev , 0 );
247300 if (mbox -> irq < 0 )
248301 return mbox -> irq ;
0 commit comments