Re: [PATCH v7 0/2] phy: bcm63xx-usbh: Add BCM63xx USBH driver

2020-07-17 Thread Simon Arlott

On 2020-07-17 10:47, Álvaro Fernández Rojas wrote:

Add BCM63xx USBH PHY driver for BMIPS.

v7: remove Simon from authors and introduce changes suggested by Rob:


I asked you to remove my email address from the source code. All you've
done is update it. I don't want spam. I know the address appears in the
commit but you don't have to spray it around everywhere else.

You can keep my name in the MODULE_AUTHOR text but you need to omit the
email address.

None of the original copyright notices included email addresses so I
don't know why you think it is appropriate for you to add them.

Please only Cc: this email address, I don't want multiple copies of
everything.

--
Simon Arlott


Re: [PATCH] ata: Disable queued TRIM for Samsung 860 SSDs

2020-07-15 Thread Simon Arlott
On 15/07/2020 21:53, Martin K. Petersen wrote:
>> Despite the unsubstantiated claim from Samsung that "the improved
>> queued trim enhances Linux compatibility" this does not appear to be
>> true, even on Intel SATA controllers:
> 
> I am aware of several people using 860 drives with queued TRIM. And I
> haven't heard any complaints outside of the bug you referenced.
> 
> Also, I have tested both 860 2.5" Pro and 860 mSATA EVO on a few
> different systems in my lab without any problems. See:
> 
> https://lore.kernel.org/stable/yq1h87du82d@oracle.com/T/

I've just checked and it happens on both my SATA 860s:
  860 EVO 2TB (RVT04B6Q) on Intel Z170
  860 PRO 1TB (RVM02B6Q) on Intel H170

> I really wish we had some more data to work with :(

Is there a reliable way of reproducing this?

I have a Marvell 88SE9235 that I could try with the EVO.

> Lacking a proper heuristic I guess we don't have any choice to disable
> the feature. But that's sad news for the people who currently don't have
> problems since their performance will inevitably suffer.

Samsung need to identify what the problem is before claiming that their
Linux support is better, especially if specific chipsets are known to
have issues...

-- 
Simon Arlott


Re: [PATCH v6 2/2] phy: bcm63xx-usbh: Add BCM63xx USBH driver

2020-07-15 Thread Simon Arlott

On 2020-07-15 14:39, Álvaro Fernández Rojas wrote:

Hello Simon,

This is based on your work:
https://github.com/nomis/linux/commit/c4c55b603a78e2732044a833e248c1a1087e7053
https://github.com/nomis/linux/commit/f153a58b9e6f88e72c3ef34dc076118f8b3ade5b


Ok, it has been a long time and I couldn't find a branch with those in 
locally.


Please remove my *email address* from the source code and MODULE_AUTHOR 
text.



Historical signed-off-by lines can be updated to:
Signed-off-by: Simon Arlott 

--
Simon Arlott


Re: [PATCH v6 2/2] phy: bcm63xx-usbh: Add BCM63xx USBH driver

2020-07-15 Thread Simon Arlott

On 2020-07-15 14:18, Álvaro Fernández Rojas wrote:

Add BCM63xx USBH PHY driver for BMIPS.

Signed-off-by: Álvaro Fernández Rojas 
---
...
+MODULE_DESCRIPTION("BCM63xx USBH PHY driver");
+MODULE_AUTHOR("Álvaro Fernández Rojas ");
+MODULE_AUTHOR("Simon Arlott ");
+MODULE_LICENSE("GPL");


I'm not the author of this.

Nacked-by: Simon Arlott 

--
Simon Arlott


[PATCH] ata: Disable queued TRIM for Samsung 860 SSDs

2020-07-15 Thread Simon Arlott
Despite the unsubstantiated claim from Samsung that "the improved
queued trim enhances Linux compatibility" this does not appear to be
true, even on Intel SATA controllers:

Bug 203475 - Samsung 860 EVO queued TRIM issues
https://bugzilla.kernel.org/show_bug.cgi?id=203475

Disable queued TRIM for all Samsung 860 SSDs. Only the EVO has been
reported as having this problem, but the original justification for
enabling appears to be based on marketing material with no explanation
of what has been changed to make the 860 work properly when the earlier
840 and 850 both have the same issue.

Signed-off-by: Simon Arlott 
Cc: Park Ju Hyung 
Cc: sta...@vger.kernel.org
Fixes: ca6bfcb2f6d9 ("libata: Enable queued TRIM for Samsung SSD 860")
---
 drivers/ata/libata-core.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index b1cd4d97bc2a..02e861aac5ec 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -3951,6 +3951,8 @@ static const struct ata_blacklist_entry 
ata_device_blacklist [] = {
ATA_HORKAGE_ZERO_AFTER_TRIM, },
{ "Samsung SSD 850*",   NULL,   ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
+   { "Samsung SSD 860*",   NULL,   ATA_HORKAGE_NO_NCQ_TRIM |
+   ATA_HORKAGE_ZERO_AFTER_TRIM, },
{ "FCCT*M500*", NULL,   ATA_HORKAGE_NO_NCQ_TRIM |
ATA_HORKAGE_ZERO_AFTER_TRIM, },
 
-- 
2.17.1

-- 
Simon Arlott


Re: [PATCH (v2)] scsi: sd: add parameter to stop disks before reboot

2020-07-15 Thread Simon Arlott

On 30/06/2020 02:35, Martin K. Petersen wrote:

What happened to the suggestion to treat reboot=p like a poweroff
instead?  That seems to be fundamentally the right thing to do.


I agree!


I've done that but so far it has been ignored:
https://lore.kernel.org/lkml/f4a7b539-eeac-1a59-2350-3eefc8c17801@0882a8b5-c6c3-11e9-b005-00805fc181fe/

--
Simon Arlott


[PATCH 2/2] x86/reboot/quirks: Add ASRock Z170 Extreme4

2020-06-29 Thread Simon Arlott
If a PCI mode reboot is performed on the ASRock Z170 Extreme4, a power
cycle will occur. Automatically set the reboot quirk for this to prepare
for the power off (i.e. stop all disks).

This will only take effect if PCI mode is manually used. It'll be too late
in the reboot process to prepare for power off if the other reboot methods
fail.

It is necessary to re-order the processing of DMI checks because this quirk
must apply even if a reboot= command line parameter is used as that's the
only way to specify a PCI mode reboot.

Signed-off-by: Simon Arlott 
---
Previous patches to make scsi/sd stop before a reboot:
https://lore.kernel.org/lkml/499138c8-b6d5-ef4a-2780-4f750ed337d3@0882a8b5-c6c3-11e9-b005-00805fc181fe/
https://lore.kernel.org/lkml/e726ffd8-8897-4a79-c3d6-6271eda8aebb@0882a8b5-c6c3-11e9-b005-00805fc181fe/

 arch/x86/kernel/reboot.c | 51 ++--
 1 file changed, 44 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 0ec7ced727fe..a82d5db1c8ca 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -147,6 +147,13 @@ STACK_FRAME_NON_STANDARD(machine_real_restart);
  */
 static int __init set_pci_reboot(const struct dmi_system_id *d)
 {
+   /*
+* Only apply the DMI-based change if reboot_type hasn't been
+* overridden on the command line.
+*/
+   if (!reboot_default)
+   return 0;
+
if (reboot_type != BOOT_CF9_FORCE) {
reboot_type = BOOT_CF9_FORCE;
pr_info("%s series board detected. Selecting %s-method for 
reboots.\n",
@@ -157,6 +164,13 @@ static int __init set_pci_reboot(const struct 
dmi_system_id *d)
 
 static int __init set_kbd_reboot(const struct dmi_system_id *d)
 {
+   /*
+* Only apply the DMI-based change if reboot_type hasn't been
+* overridden on the command line.
+*/
+   if (!reboot_default)
+   return 0;
+
if (reboot_type != BOOT_KBD) {
reboot_type = BOOT_KBD;
pr_info("%s series board detected. Selecting %s-method for 
reboot.\n",
@@ -165,6 +179,21 @@ static int __init set_kbd_reboot(const struct 
dmi_system_id *d)
return 0;
 }
 
+static int __init set_pci_power_cycle_reboot(const struct dmi_system_id *d)
+{
+   /*
+* This has to be applied even if reboot_type has been set on the
+* command line because that's the only way to enable PCI mode.
+*/
+
+   if (reboot_type == BOOT_CF9_FORCE) {
+   reboot_quirks |= REBOOT_QUIRK_POWER_CYCLE;
+   pr_info("%s series board detected. Assume that a PCI reboot 
includes a power cycle.\n",
+   d->ident);
+   }
+   return 0;
+}
+
 /*
  * This is a single dmi_table handling all reboot quirks.
  */
@@ -247,6 +276,14 @@ static const struct dmi_system_id reboot_dmi_table[] 
__initconst = {
DMI_MATCH(DMI_BOARD_NAME, "Q1900DC-ITX"),
},
},
+   {   /* PCI reboots cause a power cycle */
+   .callback = set_pci_power_cycle_reboot,
+   .ident = "ASRock Z170 Extreme4",
+   .matches = {
+   DMI_MATCH(DMI_BOARD_VENDOR, "ASRock"),
+   DMI_MATCH(DMI_BOARD_NAME, "Z170 Extreme4"),
+   },
+   },
 
/* ASUS */
{   /* Handle problems with rebooting on ASUS P4S800 */
@@ -494,13 +531,6 @@ static int __init reboot_init(void)
 {
int rv;
 
-   /*
-* Only do the DMI check if reboot_type hasn't been overridden
-* on the command line
-*/
-   if (!reboot_default)
-   return 0;
-
/*
 * The DMI quirks table takes precedence. If no quirks entry
 * matches and the ACPI Hardware Reduced bit is set and EFI
@@ -508,6 +538,13 @@ static int __init reboot_init(void)
 */
rv = dmi_check_system(reboot_dmi_table);
 
+   /*
+* Only force EFI reboot if reboot_type hasn't been overridden
+* on the command line.
+*/
+   if (!reboot_default)
+   return 0;
+
if (!rv && efi_reboot_required() && !efi_runtime_disabled())
reboot_type = BOOT_EFI;
 
-- 
2.17.1

-- 
Simon Arlott


[PATCH 1/2] reboot: add a "power cycle" quirk to prepare for a power off on reboot

2020-06-29 Thread Simon Arlott
I need to use "reboot=p" on my desktop because one of the PCIe devices
does not appear after a warm boot. This results in a very cold boot
because the BIOS turns the PSU off and on.

The scsi sd shutdown process does not send a stop command to disks
before the reboot happens (stop commands are only sent for a shutdown).

The result is that all of my SSDs experience a sudden power loss on
every reboot, which is undesirable behaviour because it could cause data
to be corrupted. These events are recorded in the SMART attributes.

Add a "power cycle" quirk to the reboot options to prepare all devices for
a power off by setting the system_state to SYSTEM_POWER_OFF instead of
SYSTEM_RESTART while still performing a restart as requested.

This uses the letter "C" for the parameter because of numerous uses of
"reboot=pci" that would otherwise trigger this behaviour if "c" was used.

Signed-off-by: Simon Arlott 
---
Previous patches to make scsi/sd stop before a reboot:
https://lore.kernel.org/lkml/499138c8-b6d5-ef4a-2780-4f750ed337d3@0882a8b5-c6c3-11e9-b005-00805fc181fe/
https://lore.kernel.org/lkml/e726ffd8-8897-4a79-c3d6-6271eda8aebb@0882a8b5-c6c3-11e9-b005-00805fc181fe/

 Documentation/admin-guide/kernel-parameters.txt |  8 ++--
 include/linux/reboot.h  |  4 
 kernel/reboot.c | 15 ++-
 3 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt 
b/Documentation/admin-guide/kernel-parameters.txt
index bee3b83d6f84..91359fd4fbcc 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -4422,9 +4422,10 @@
reboot= [KNL]
Format (x86 or x86_64):
[w[arm] | c[old] | h[ard] | s[oft] | g[pio]] \
-   [[,]s[mp] \
+   [[,]s[mp]] \
[[,]b[ios] | a[cpi] | k[bd] | t[riple] | e[fi] 
| p[ci]] \
-   [[,]f[orce]
+   [[,]f[orce]] \
+   [[,]C]
Where reboot_mode is one of warm (soft) or cold (hard) 
or gpio
(prefix with 'panic_' to set mode for 
panic
reboot only),
@@ -4432,6 +4433,9 @@
  reboot_force is either force or not specified,
  reboot_cpu is s[mp] with  being the 
processor
to be used for rebooting.
+   Quirks:
+   C = Rebooting includes a power cycle, prepare
+   for a power off instead of a restart.
 
refscale.holdoff= [KNL]
Set test-start holdoff period.  The purpose of
diff --git a/include/linux/reboot.h b/include/linux/reboot.h
index 3734cd8f38a8..b49559ba825a 100644
--- a/include/linux/reboot.h
+++ b/include/linux/reboot.h
@@ -39,6 +39,10 @@ extern int reboot_default;
 extern int reboot_cpu;
 extern int reboot_force;
 
+#define REBOOT_QUIRK_POWER_CYCLEBIT(0)
+
+extern int reboot_quirks;
+
 
 extern int register_reboot_notifier(struct notifier_block *);
 extern int unregister_reboot_notifier(struct notifier_block *);
diff --git a/kernel/reboot.c b/kernel/reboot.c
index 491f1347bf43..5605c2894f2b 100644
--- a/kernel/reboot.c
+++ b/kernel/reboot.c
@@ -45,6 +45,7 @@ int reboot_default = 1;
 int reboot_cpu;
 enum reboot_type reboot_type = BOOT_ACPI;
 int reboot_force;
+int reboot_quirks;
 
 /*
  * If set, this is used for preparing the system to power off.
@@ -71,7 +72,15 @@ EXPORT_SYMBOL_GPL(emergency_restart);
 void kernel_restart_prepare(char *cmd)
 {
blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd);
-   system_state = SYSTEM_RESTART;
+   if (reboot_quirks & REBOOT_QUIRK_POWER_CYCLE) {
+   /*
+* The reboot will include a power cycle, so prepare all
+* devices for a power off.
+*/
+   system_state = SYSTEM_POWER_OFF;
+   } else {
+   system_state = SYSTEM_RESTART;
+   }
usermodehelper_disable();
device_shutdown();
 }
@@ -583,6 +592,10 @@ static int __init reboot_setup(char *str)
case 'f':
reboot_force = 1;
break;
+
+   case 'C':
+   reboot_quirks |= REBOOT_QUIRK_POWER_CYCLE;
+   break;
}
 
str = strchr(str, ',');
-- 
2.17.1

-- 
Simon Arlott


[PATCH (v2)] scsi: sd: add parameter to stop disks before reboot

2020-06-28 Thread Simon Arlott
I need to use "reboot=p" on my desktop because one of the PCIe devices
does not appear after a warm boot. This results in a very cold boot
because the BIOS turns the PSU off and on.

The scsi sd shutdown process does not send a stop command to disks
before the reboot happens (stop commands are only sent for a shutdown).

The result is that all of my SSDs experience a sudden power loss on
every reboot, which is undesirable behaviour because it could cause data
to be corrupted. These events are recorded in the SMART attributes.

Add a "stop_before_reboot" module parameter that can be used to control
the shutdown behaviour of disks before a reboot. The default will be
the existing behaviour (disks are not stopped).

  sd_mod.stop_before_reboot=
0 = disabled (default)
1 = enabled

The behaviour on shutdown is unchanged: all disks are unconditionally
stopped.

Signed-off-by: Simon Arlott 
---
 Documentation/scsi/scsi-parameters.rst |  5 +
 drivers/scsi/sd.c  | 14 +++---
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/Documentation/scsi/scsi-parameters.rst 
b/Documentation/scsi/scsi-parameters.rst
index 9aba897c97ac..324610870de5 100644
--- a/Documentation/scsi/scsi-parameters.rst
+++ b/Documentation/scsi/scsi-parameters.rst
@@ -101,6 +101,11 @@ parameters may be changed at runtime by the command
allowing boot to proceed.  none ignores them, expecting
user space to do the scan.
 
+   sd_mod.stop_before_reboot=
+   [SCSI] configure stop action for disks before a reboot
+   Format: 
+   0 = disabled (default), 1 = enabled
+
sim710= [SCSI,HW]
See header of drivers/scsi/sim710.c.
 
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index d90fefffe31b..506904bf15da 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -98,6 +98,12 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_MOD);
 MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
 MODULE_ALIAS_SCSI_DEVICE(TYPE_ZBC);
 
+static unsigned int stop_before_reboot = 0;
+
+module_param(stop_before_reboot, uint, 0644);
+MODULE_PARM_DESC(stop_before_reboot,
+"stop disks before reboot");
+
 #if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
 #define SD_MINORS  16
 #else
@@ -3576,9 +3582,11 @@ static void sd_shutdown(struct device *dev)
sd_sync_cache(sdkp, NULL);
}
 
-   if (system_state != SYSTEM_RESTART && sdkp->device->manage_start_stop) {
-   sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
-   sd_start_stop_device(sdkp, 0);
+   if (sdkp->device->manage_start_stop) {
+   if (system_state != SYSTEM_RESTART || stop_before_reboot) {
+   sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
+   sd_start_stop_device(sdkp, 0);
+   }
}
 }
 
-- 
2.17.1

-- 
Simon Arlott


Re: [PATCH] scsi: sd: stop SSD (non-rotational) disks before reboot

2020-06-28 Thread Simon Arlott
On 23/06/2020 21:42, Henrique de Moraes Holschuh wrote:
> [1] I have long lost the will and energy to pursue this, so *this* is a
> throw-away anecdote for anyone that cares: I reported here a few years
> ago that many models of *SATA* based SSDs from Crucial/Micron, Samsung
> and Intel were complaining (through their SMART attributes) that Linux
> was causing unsafe shutdowns.
> 
> https://lkml.org/lkml/2017/4/10/1181
> 
> TL;DR: wait one *extra* second after the SSD acknowleged the STOP
> command as complete before you trust the SSD device is safe to be
> powered down (i.e. before reboot, suspend, poweroff/shutdown, and device
> removal/detach).  This worked around the issue for every vendor and
> model of SSD we tested.

Looking through that thread, it looks like a simple 1 second delay on
shutdown/reboot patch hasn't been proposed yet?

In my case none of the SSDs are recording unexpected power loss if they
are stopped before the reboot, but the reboot won't necessarily be
instantaneous after the last stop command returns.

-- 
Simon Arlott


Re: [PATCH] scsi: sd: stop SSD (non-rotational) disks before reboot

2020-06-28 Thread Simon Arlott
On 19/06/2020 00:31, Damien Le Moal wrote:
> On 2020/06/18 21:26, Simon Arlott wrote:
>> I haven't verified it, but the BIOS leaves the power off for several
>> seconds which should be long enough for the HDDs to spin down.
>> 
>> I'm less concerned about those suddenly losing power but it would be
>> nice to have a stop command sent to them too.
> 
> OK. So maybe the patch should be as simple as changing SYSTEM_RESTART state to
> SYSTEM_POWER_OFF if reboot=p is set, no ? Since that is consistent with the 
> fact
> that reboot=p will cause power to go off, exactly the same as a regular
> shutdown, it seems cleaner and safer to use SYSTEM_POWER_OFF for the entire
> system, not just scsi disks.

That could be a bit misleading because the power isn't going to stay
off. Some of the network drivers have specific WOL behaviour changes
for a power off.

Power cycling the PSU is not something that every BIOS will do, so it's
not that simple. It could be a module parameter but I'd be concerned
that some other code will assuming the system should be powered off and
all of my reboots will become power off events.

-- 
Simon Arlott


Re: [PATCH] scsi: sd: stop SSD (non-rotational) disks before reboot

2020-06-28 Thread Simon Arlott
On 23/06/2020 14:36, Pavel Machek wrote:
> Many SSDs are buggy, and will eventually corrupt themselves if you do enough
> sudden power loss experiments.
> 
> HDDs don't like their power cut, either. You can hear the difference 
> between normal power off and power cut...

I will change the patch so that it doesn't distinguish between types of
disks.

The default will have to be the existing behaviour (don't stop disks)
because most reboots shouldn't result in a loss of power.

-- 
Simon Arlott


Re: [PATCH] scsi: sd: stop SSD (non-rotational) disks before reboot

2020-06-18 Thread Simon Arlott
On 18/06/2020 08:21, Christoph Hellwig wrote:
> On Wed, Jun 17, 2020 at 07:49:57PM +0100, Simon Arlott wrote:
>> Avoiding a stop of the disk on a reboot is appropriate for HDDs because
>> they're likely to continue to be powered (and should not be told to spin
>> down only to spin up again) but the default behaviour for SSDs should
>> be changed to stop them before the reboot.
> 
> I don't think that is true in general.  At least for most current server
> class and older desktop and laptop class systems they use the same
> format factors and enclosures, although they are slightly divering now.
> 
> So I think this needs to be quirked based on the platform and/or
> enclosure.

Are you referring to the behaviour for handling HDDs or SSDs?

For HDDs, the default "1" option could mean "automatic" and apply to
rotational disks when power loss is expected.

For SSDs, I don't think an extra stop should ever be an issue.

-- 
Simon Arlott


Re: [PATCH] scsi: sd: stop SSD (non-rotational) disks before reboot

2020-06-18 Thread Simon Arlott
On 18/06/2020 09:36, Damien Le Moal wrote:
> On 2020/06/18 3:50, Simon Arlott wrote:
>> I need to use "reboot=p" on my desktop because one of the PCIe devices
>> does not appear after a warm boot. This results in a very cold boot
>> because the BIOS turns the PSU off and on.
>> 
>> The scsi sd shutdown process does not send a stop command to disks
>> before the reboot happens (stop commands are only sent for a shutdown).
>> 
>> The result is that all of my SSDs experience a sudden power loss on
>> every reboot, which is undesirable behaviour. These events are recorded
>> in the SMART attributes.
> 
> Why is it undesirable for an SSD ? The sequence you are describing is not
> different from doing "shutdown -h now" and then pressing down the power button
> again immediately after power is cut...

On a shutdown the kernel will send a stop command to the SSD. It does
not currently do this for a reboot so I observe the unexpected power
loss counters increasing.

> Are you experiencing data loss or corruption ? If yes, since a clean reboot or
> shutdown issues a synchronize cache to all devices, a corruption would mean 
> that
> your SSD is probably not correctly processing flush cache commands.

No, I'm not experiencing any data loss or corruption that I'm aware of.

We can argue whether or not any given SSD correctly processes commands
to flush the cache, but they are expecting to be stopped before power
is removed.

>> Avoiding a stop of the disk on a reboot is appropriate for HDDs because
>> they're likely to continue to be powered (and should not be told to spin
>> down only to spin up again) but the default behaviour for SSDs should
>> be changed to stop them before the reboot.
> 
> If your BIOS turns the PSU down and up, then the HDDs too will lose power... 
> The
> difference will be that the disks will still be spinning from inertia on the
> power up, and so the HDD spin up processing will be faster than for a pure 
> cold
> boot sequence.

I haven't verified it, but the BIOS leaves the power off for several
seconds which should be long enough for the HDDs to spin down.

I'm less concerned about those suddenly losing power but it would be
nice to have a stop command sent to them too.

-- 
Simon Arlott


Re: [PATCH] scsi: sd: stop SSD (non-rotational) disks before reboot

2020-06-17 Thread Simon Arlott
On 17/06/2020 20:19, Bart Van Assche wrote:
> On 2020-06-17 11:49, Simon Arlott wrote:
>> @@ -3576,9 +3582,19 @@ static void sd_shutdown(struct device *dev)
>>  sd_sync_cache(sdkp, NULL);
>>  }
>>  
>> -if (system_state != SYSTEM_RESTART && sdkp->device->manage_start_stop) {
>> -sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
>> -sd_start_stop_device(sdkp, 0);
>> +if (sdkp->device->manage_start_stop) {
>> +bool stop_disk = (system_state != SYSTEM_RESTART);
>> +
>> +if (stop_before_reboot > 1) { /* stop all disks */
>> +stop_disk = true;
>> +} else if (stop_before_reboot) { /* non-rotational only */
>> +stop_disk |= blk_queue_nonrot(sdkp->disk->queue);
>> +}
>> +
>> +if (stop_disk) {
>> +sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
>> +sd_start_stop_device(sdkp, 0);
>> +}
>>  }
>>  }
> 
> Is introduction of a new kernel module parameter essential?

It is system-dependent whether or not a reboot is going to result in a
loss of power, so it's required to be able to stop the HDDs too.

They're already always stopped on shutdown where power is definitely
going to be lost. I can't do that by default on a reboot because the
usual convention is that the power stays on during a reboot and it would
be expected that the HDDs keep spinning.

> Or in other
> words, has it been considered to apply the new behavior to all SSDs?

The default value is 1, so it does apply to all SSDs. I want to be able
to configure it to apply to HDDs too.

-- 
Simon Arlott


[PATCH] scsi: sd: stop SSD (non-rotational) disks before reboot

2020-06-17 Thread Simon Arlott
I need to use "reboot=p" on my desktop because one of the PCIe devices
does not appear after a warm boot. This results in a very cold boot
because the BIOS turns the PSU off and on.

The scsi sd shutdown process does not send a stop command to disks
before the reboot happens (stop commands are only sent for a shutdown).

The result is that all of my SSDs experience a sudden power loss on
every reboot, which is undesirable behaviour. These events are recorded
in the SMART attributes.

Avoiding a stop of the disk on a reboot is appropriate for HDDs because
they're likely to continue to be powered (and should not be told to spin
down only to spin up again) but the default behaviour for SSDs should
be changed to stop them before the reboot.

Add a "stop_before_reboot" module parameter that can be used to control
the shutdown behaviour of disks before a reboot. The default will be
to stop non-rotational disks (SSDs) only, but it can be configured to
stop all disks if it is known that power will be lost completely on a
reboot.

  sd_mod.stop_before_reboot=
0 = never
1 = non-rotational disks only (default)
2 = all disks

The behaviour on shutdown is unchanged: all disks are unconditionally
stopped.

The disk I/O will be mostly quiescent at reboot time (and there is a
sync first) but this should be added to stable kernels to protect all
SSDs from unexpected power loss during a reboot by default. There is
the potential for an unexpected power loss to corrupt data depending
on the SSD model/firmware.

Cc: sta...@vger.kernel.org
Signed-off-by: Simon Arlott 
---
 Documentation/scsi/scsi-parameters.rst |  7 +++
 drivers/scsi/sd.c  | 22 +++---
 2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/Documentation/scsi/scsi-parameters.rst 
b/Documentation/scsi/scsi-parameters.rst
index 9aba897c97ac..fd64d0d43861 100644
--- a/Documentation/scsi/scsi-parameters.rst
+++ b/Documentation/scsi/scsi-parameters.rst
@@ -101,6 +101,13 @@ parameters may be changed at runtime by the command
allowing boot to proceed.  none ignores them, expecting
user space to do the scan.
 
+   sd_mod.stop_before_reboot=
+   [SCSI] configure stop action for disks before a reboot
+   Format: 
+   0 = never
+   1 = non-rotational disks only (default)
+   2 = all disks
+
sim710= [SCSI,HW]
See header of drivers/scsi/sim710.c.
 
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index d90fefffe31b..1cd652e037ab 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -98,6 +98,12 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_MOD);
 MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC);
 MODULE_ALIAS_SCSI_DEVICE(TYPE_ZBC);
 
+static unsigned int stop_before_reboot = 1;
+
+module_param(stop_before_reboot, uint, 0644);
+MODULE_PARM_DESC(stop_before_reboot,
+"stop disks before reboot (1=non-rotational, 2=all)");
+
 #if !defined(CONFIG_DEBUG_BLOCK_EXT_DEVT)
 #define SD_MINORS  16
 #else
@@ -3576,9 +3582,19 @@ static void sd_shutdown(struct device *dev)
sd_sync_cache(sdkp, NULL);
}
 
-   if (system_state != SYSTEM_RESTART && sdkp->device->manage_start_stop) {
-   sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
-   sd_start_stop_device(sdkp, 0);
+   if (sdkp->device->manage_start_stop) {
+   bool stop_disk = (system_state != SYSTEM_RESTART);
+
+   if (stop_before_reboot > 1) { /* stop all disks */
+   stop_disk = true;
+   } else if (stop_before_reboot) { /* non-rotational only */
+   stop_disk |= blk_queue_nonrot(sdkp->disk->queue);
+   }
+
+   if (stop_disk) {
+   sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
+   sd_start_stop_device(sdkp, 0);
+   }
}
 }
 
-- 
2.17.1

-- 
Simon Arlott


[PATCH v2 2/2] scsi: sr: Fix sr_probe() missing deallocate of device minor

2020-05-30 Thread Simon Arlott
If the cdrom fails to be registered then the device minor should be
deallocated.

Signed-off-by: Simon Arlott 
Cc: sta...@vger.kernel.org
---
On 30/05/2020 17:24, Bart Van Assche wrote:
> On 2020-05-30 02:33, Simon Arlott wrote:
>> If the cdrom fails to be registered then the device minor should be
>> deallocated.
> 
> Also for this patch, please add Fixes: and Cc: stable tags.

I've Cc:'d stable.

There is no specific previous commit that this fixes. I was just
checking the rest of sr_probe when making a patch for the first issue.

 drivers/scsi/sr.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 8d062d4f3ce0..1e13c6a0f0ca 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -797,7 +797,7 @@ static int sr_probe(struct device *dev)
cd->cdi.disk = disk;
 
if (register_cdrom(&cd->cdi))
-   goto fail_put;
+   goto fail_minor;
 
/*
 * Initialize block layer runtime PM stuffs before the
@@ -815,6 +815,10 @@ static int sr_probe(struct device *dev)
 
return 0;
 
+fail_minor:
+   spin_lock(&sr_index_lock);
+   clear_bit(minor, sr_index_bits);
+   spin_unlock(&sr_index_lock);
 fail_put:
put_disk(disk);
    mutex_destroy(&cd->lock);
-- 
2.17.1

-- 
Simon Arlott


[PATCH v2 1/2] scsi: sr: Fix sr_probe() missing mutex_destroy

2020-05-30 Thread Simon Arlott
If the device minor cannot be allocated or the cdrom fails to be
registered then the mutex should be destroyed.

Signed-off-by: Simon Arlott 
Fixes: 51a858817dcd ("scsi: sr: get rid of sr global mutex")
Cc: sta...@vger.kernel.org
---
On 30/05/2020 17:41, James Bottomley wrote:
> On Sat, 2020-05-30 at 09:24 -0700, Bart Van Assche wrote:
>> Please add Fixes: and Cc: stable tags.

I've added a Fixes: tag and Cc:'d stable.

> This isn't really a bug, is it?  mutex_destroy is a nop unless lock
> debugging is enabled in which case it checks the lock is unlocked and
> marks it as unusable to detect a use after destroy.  Since the
> structure containing the mutex is kfree'd in the next statement, kasan
> would also detect any use after free.  That's not to say we shouldn't
> do this to be fully correct ... just that it has no potential ever to
> have user visible impact so there doesn't seem to be much point
> cluttering up the stable process with it.

If the current lock debugging implementation in stable will be ok with
it then I'd agree there's no reason to put it in stable kernels, except
that the commit this fixes was added to stable with this bug and one in
sr_block_release (72655c0ebd1d).

 drivers/scsi/sr.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index d2fe3fa470f9..8d062d4f3ce0 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -817,6 +817,7 @@ static int sr_probe(struct device *dev)
 
 fail_put:
put_disk(disk);
+   mutex_destroy(&cd->lock);
 fail_free:
kfree(cd);
 fail:
-- 
2.17.1

-- 
Simon Arlott


[PATCH 2/2] scsi: sr: Fix sr_probe() missing deallocate of device minor

2020-05-30 Thread Simon Arlott
If the cdrom fails to be registered then the device minor should be
deallocated.

Signed-off-by: Simon Arlott 
---
 drivers/scsi/sr.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 8d062d4f3ce0..1e13c6a0f0ca 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -797,7 +797,7 @@ static int sr_probe(struct device *dev)
cd->cdi.disk = disk;
 
if (register_cdrom(&cd->cdi))
-   goto fail_put;
+   goto fail_minor;
 
/*
 * Initialize block layer runtime PM stuffs before the
@@ -815,6 +815,10 @@ static int sr_probe(struct device *dev)
 
return 0;
 
+fail_minor:
+   spin_lock(&sr_index_lock);
+   clear_bit(minor, sr_index_bits);
+   spin_unlock(&sr_index_lock);
 fail_put:
put_disk(disk);
mutex_destroy(&cd->lock);
-- 
2.17.1

-- 
Simon Arlott


[PATCH 1/2] scsi: sr: Fix sr_probe() missing mutex_destroy

2020-05-30 Thread Simon Arlott
If the device minor cannot be allocated or the cdrom fails to be
registered then the mutex should be destroyed.

Signed-off-by: Simon Arlott 
---
 drivers/scsi/sr.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index d2fe3fa470f9..8d062d4f3ce0 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -817,6 +817,7 @@ static int sr_probe(struct device *dev)
 
 fail_put:
put_disk(disk);
+   mutex_destroy(&cd->lock);
 fail_free:
kfree(cd);
 fail:
-- 
2.17.1

-- 
Simon Arlott


[PATCH] mailmap: Add Simon Arlott (replacement for expired email address)

2019-08-22 Thread Simon Arlott
Add replacement email address for the one on my expired domain.

Signed-off-by: Simon Arlott 
---
I'd prefer not to be in this "list of email addresses to spam" but it
appears to be the only way to stop people searching for other addresses
to misuse after I had to let my domain expire:

"Where, as of the withdrawal date and as a result of the withdrawal of
the United Kingdom, a holder of a domain name does no longer fulfil the
general eligibility criteria pursuant to Article 4(2)(b) of Regulation
(EC) 733/2002, the Registry for .eu will be entitled to revoke such
domain name on its own initiative and without submitting the dispute to
any extrajudicial settlement of conflicts in accordance with point (b)
of Article 20, first subparagraph, of Commission Regulation (EC) No
874/2004."

 .mailmap | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.mailmap b/.mailmap
index acba1a6163f1..468e328ee572 100644
--- a/.mailmap
+++ b/.mailmap
@@ -214,6 +214,7 @@ Shuah Khan  
 Shuah Khan  
 Shuah Khan  
 Shuah Khan  
+Simon Arlott  
 Simon Kelley 
 Stéphane Witzmann 
 Stephen Hemminger 
-- 
2.17.1

-- 
Simon Arlott


[tip:irq/core] irqchips/bmips: Add bcm6345-l1 interrupt controller

2016-02-08 Thread tip-bot for Simon Arlott
Commit-ID:  c7c42ec2baa1de7ab3965e4f1bf5073bee6065e4
Gitweb: http://git.kernel.org/tip/c7c42ec2baa1de7ab3965e4f1bf5073bee6065e4
Author: Simon Arlott 
AuthorDate: Sun, 22 Nov 2015 14:30:14 +
Committer:  Thomas Gleixner 
CommitDate: Mon, 8 Feb 2016 15:03:42 +0100

irqchips/bmips: Add bcm6345-l1 interrupt controller

Add the BCM6345 interrupt controller based on the SMP-capable BCM7038
and the BCM3380 but with packed interrupt registers.

Add the BCM6345 interrupt controller to a list with the existing BCM7038
so that interrupts on CPU1 are not ignored.

Update the maintainers file list for BMIPS to include this driver.

Signed-off-by: Simon Arlott 
Cc: Mark Rutland 
Cc: devicet...@vger.kernel.org
Cc: Ian Campbell 
Cc: Florian Fainelli 
Cc: Jason Cooper 
Cc: Pawel Moll 
Cc: linux-m...@linux-mips.org
Cc: Marc Zyngier 
Cc: Kevin Cernekee 
Cc: Ralf Baechle 
Cc: Jonas Gorski 
Cc: Kumar Gala 
Cc: Rob Herring 
Link: http://lkml.kernel.org/r/5651d176.6030...@simon.arlott.org.uk
Signed-off-by: Thomas Gleixner 
---
 MAINTAINERS  |   1 +
 arch/mips/Kconfig|   1 +
 arch/mips/bmips/irq.c|  10 +-
 drivers/irqchip/Kconfig  |   5 +
 drivers/irqchip/Makefile |   1 +
 drivers/irqchip/irq-bcm6345-l1.c | 364 +++
 6 files changed, 380 insertions(+), 2 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 7f1fa4f..b5fab14f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2423,6 +2423,7 @@ F:arch/mips/bmips/*
 F: arch/mips/include/asm/mach-bmips/*
 F: arch/mips/kernel/*bmips*
 F: arch/mips/boot/dts/brcm/bcm*.dts*
+F: drivers/irqchip/irq-bcm63*
 F: drivers/irqchip/irq-bcm7*
 F: drivers/irqchip/irq-brcmstb*
 F: include/linux/bcm963xx_nvram.h
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 57a945e..eb079ac 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -151,6 +151,7 @@ config BMIPS_GENERIC
select CSRC_R4K
select SYNC_R4K
select COMMON_CLK
+   select BCM6345_L1_IRQ
select BCM7038_L1_IRQ
select BCM7120_L2_IRQ
select BRCMSTB_L2_IRQ
diff --git a/arch/mips/bmips/irq.c b/arch/mips/bmips/irq.c
index e7fc6f934..7efefcf 100644
--- a/arch/mips/bmips/irq.c
+++ b/arch/mips/bmips/irq.c
@@ -15,6 +15,12 @@
 #include 
 #include 
 
+static const struct of_device_id smp_intc_dt_match[] = {
+   { .compatible = "brcm,bcm7038-l1-intc" },
+   { .compatible = "brcm,bcm6345-l1-intc" },
+   {}
+};
+
 unsigned int get_c0_compare_int(void)
 {
return CP0_LEGACY_COMPARE_IRQ;
@@ -24,8 +30,8 @@ void __init arch_init_irq(void)
 {
struct device_node *dn;
 
-   /* Only the STB (bcm7038) controller supports SMP IRQ affinity */
-   dn = of_find_compatible_node(NULL, NULL, "brcm,bcm7038-l1-intc");
+   /* Only these controllers support SMP IRQ affinity */
+   dn = of_find_matching_node(NULL, smp_intc_dt_match);
if (dn)
of_node_put(dn);
else
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index fb50911..abe7a57 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -78,6 +78,11 @@ config I8259
bool
select IRQ_DOMAIN
 
+config BCM6345_L1_IRQ
+   bool
+   select GENERIC_IRQ_CHIP
+   select IRQ_DOMAIN
+
 config BCM7038_L1_IRQ
bool
select GENERIC_IRQ_CHIP
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 18caacb..d91d99d 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_XTENSA)  += irq-xtensa-pic.o
 obj-$(CONFIG_XTENSA_MX)+= irq-xtensa-mx.o
 obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o
 obj-$(CONFIG_SOC_VF610)+= irq-vf610-mscm-ir.o
+obj-$(CONFIG_BCM6345_L1_IRQ)   += irq-bcm6345-l1.o
 obj-$(CONFIG_BCM7038_L1_IRQ)   += irq-bcm7038-l1.o
 obj-$(CONFIG_BCM7120_L2_IRQ)   += irq-bcm7120-l2.o
 obj-$(CONFIG_BRCMSTB_L2_IRQ)   += irq-brcmstb-l2.o
diff --git a/drivers/irqchip/irq-bcm6345-l1.c b/drivers/irqchip/irq-bcm6345-l1.c
new file mode 100644
index 000..b844c89
--- /dev/null
+++ b/drivers/irqchip/irq-bcm6345-l1.c
@@ -0,0 +1,364 @@
+/*
+ * Broadcom BCM6345 style Level 1 interrupt controller driver
+ *
+ * Copyright (C) 2014 Broadcom Corporation
+ * Copyright 2015 Simon Arlott
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This is based on the BCM7038 (which supports SMP) but with a single
+ * enable register instead of separate mask/set/clear registers.
+ *
+ * The BCM3380 has a similar mask/status register layout, but each pair
+ * of words is at separate locations (and SMP is not supported).
+ *
+ * ENABLE/STATUS words are packed next to each other

[tip:irq/core] irqchips/bmips: Add bcm6345-l1 interrupt controller

2016-02-08 Thread tip-bot for Simon Arlott
Commit-ID:  64e1741f92191a9d8c3949eff48a4670b440c9f8
Gitweb: http://git.kernel.org/tip/64e1741f92191a9d8c3949eff48a4670b440c9f8
Author: Simon Arlott 
AuthorDate: Sun, 22 Nov 2015 14:30:14 +
Committer:  Thomas Gleixner 
CommitDate: Mon, 8 Feb 2016 11:45:21 +0100

irqchips/bmips: Add bcm6345-l1 interrupt controller

Add the BCM6345 interrupt controller based on the SMP-capable BCM7038
and the BCM3380 but with packed interrupt registers.

Add the BCM6345 interrupt controller to a list with the existing BCM7038
so that interrupts on CPU1 are not ignored.

Update the maintainers file list for BMIPS to include this driver.

Signed-off-by: Simon Arlott 
Cc: Mark Rutland 
Cc: devicet...@vger.kernel.org
Cc: Ian Campbell 
Cc: Florian Fainelli 
Cc: Jason Cooper 
Cc: Pawel Moll 
Cc: linux-m...@linux-mips.org
Cc: Marc Zyngier 
Cc: Kevin Cernekee 
Cc: Ralf Baechle 
Cc: Jonas Gorski 
Cc: Kumar Gala 
Cc: Rob Herring 
Link: http://lkml.kernel.org/r/5651d176.6030...@simon.arlott.org.uk
Signed-off-by: Thomas Gleixner 
---
 MAINTAINERS  |   1 +
 arch/mips/Kconfig|   1 +
 arch/mips/bmips/irq.c|  10 +-
 drivers/irqchip/Kconfig  |   5 +
 drivers/irqchip/Makefile |   1 +
 drivers/irqchip/irq-bcm6345-l1.c | 364 +++
 6 files changed, 380 insertions(+), 2 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 7f1fa4f..b5fab14f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2423,6 +2423,7 @@ F:arch/mips/bmips/*
 F: arch/mips/include/asm/mach-bmips/*
 F: arch/mips/kernel/*bmips*
 F: arch/mips/boot/dts/brcm/bcm*.dts*
+F: drivers/irqchip/irq-bcm63*
 F: drivers/irqchip/irq-bcm7*
 F: drivers/irqchip/irq-brcmstb*
 F: include/linux/bcm963xx_nvram.h
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 57a945e..eb079ac 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -151,6 +151,7 @@ config BMIPS_GENERIC
select CSRC_R4K
select SYNC_R4K
select COMMON_CLK
+   select BCM6345_L1_IRQ
select BCM7038_L1_IRQ
select BCM7120_L2_IRQ
select BRCMSTB_L2_IRQ
diff --git a/arch/mips/bmips/irq.c b/arch/mips/bmips/irq.c
index e7fc6f934..7efefcf 100644
--- a/arch/mips/bmips/irq.c
+++ b/arch/mips/bmips/irq.c
@@ -15,6 +15,12 @@
 #include 
 #include 
 
+static const struct of_device_id smp_intc_dt_match[] = {
+   { .compatible = "brcm,bcm7038-l1-intc" },
+   { .compatible = "brcm,bcm6345-l1-intc" },
+   {}
+};
+
 unsigned int get_c0_compare_int(void)
 {
return CP0_LEGACY_COMPARE_IRQ;
@@ -24,8 +30,8 @@ void __init arch_init_irq(void)
 {
struct device_node *dn;
 
-   /* Only the STB (bcm7038) controller supports SMP IRQ affinity */
-   dn = of_find_compatible_node(NULL, NULL, "brcm,bcm7038-l1-intc");
+   /* Only these controllers support SMP IRQ affinity */
+   dn = of_find_matching_node(NULL, smp_intc_dt_match);
if (dn)
of_node_put(dn);
else
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index fb50911..abe7a57 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -78,6 +78,11 @@ config I8259
bool
select IRQ_DOMAIN
 
+config BCM6345_L1_IRQ
+   bool
+   select GENERIC_IRQ_CHIP
+   select IRQ_DOMAIN
+
 config BCM7038_L1_IRQ
bool
select GENERIC_IRQ_CHIP
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 18caacb..d91d99d 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -46,6 +46,7 @@ obj-$(CONFIG_XTENSA)  += irq-xtensa-pic.o
 obj-$(CONFIG_XTENSA_MX)+= irq-xtensa-mx.o
 obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o
 obj-$(CONFIG_SOC_VF610)+= irq-vf610-mscm-ir.o
+obj-$(CONFIG_BCM6345_L1_IRQ)   += irq-bcm6345-l1.o
 obj-$(CONFIG_BCM7038_L1_IRQ)   += irq-bcm7038-l1.o
 obj-$(CONFIG_BCM7120_L2_IRQ)   += irq-bcm7120-l2.o
 obj-$(CONFIG_BRCMSTB_L2_IRQ)   += irq-brcmstb-l2.o
diff --git a/drivers/irqchip/irq-bcm6345-l1.c b/drivers/irqchip/irq-bcm6345-l1.c
new file mode 100644
index 000..b844c89
--- /dev/null
+++ b/drivers/irqchip/irq-bcm6345-l1.c
@@ -0,0 +1,364 @@
+/*
+ * Broadcom BCM6345 style Level 1 interrupt controller driver
+ *
+ * Copyright (C) 2014 Broadcom Corporation
+ * Copyright 2015 Simon Arlott
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This is based on the BCM7038 (which supports SMP) but with a single
+ * enable register instead of separate mask/set/clear registers.
+ *
+ * The BCM3380 has a similar mask/status register layout, but each pair
+ * of words is at separate locations (and SMP is not supported).
+ *
+ * ENABLE/STATUS words are packed next to each other

[PATCH linux-next v4 11/11] mtd: bcm63xxpart: Add NAND partitioning support

2015-12-13 Thread Simon Arlott
Add partitioning support for BCM963xx boards with NAND flash.

The following partitions are defined:
  "boot":   CFE and nvram data
  "rootfs": Currently selected rootfs
  "data":   Configuration data
  "rootfs1_update": Container for the whole flash area used
for the first rootfs to allow it to be
updated
  "rootfs2_update": Container for the whole flash area used
for the second rootfs to allow it to be
updated
  "rootfs_other":   The other (not currently selected) rootfs

Example:
[2.157094] nand: device found, Manufacturer ID: 0xc2, Chip ID: 0xf1
[2.163796] nand: Macronix NAND 128MiB 3,3V 8-bit
[2.168648] nand: 128 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB 
size: 64
[2.176588] bcm6368_nand 1200.nand: detected 128MiB total, 128KiB 
blocks, 2KiB pages, 16B OOB, 8-bit, Hamming ECC
[2.189782] Bad block table found at page 65472, version 0x01
[2.196910] Bad block table found at page 65408, version 0x01
[2.204003] nand_read_bbt: bad block at 0x0748
[2.225220] bcm63xxpart: rootfs1: CFE image tag found at 0x2 with 
version 6, board type 963168VX
[2.236188] bcm63xxpart: rootfs2: CFE image tag found at 0x400 with 
version 6, board type 963168VX
[2.246165] bcm63xxpart: CFE bootline selected latest image rootfs1 
(rootfs1_seq=2, rootfs2_seq=1)
[2.255800] 6 bcm63xxpart partitions found on MTD device brcmnand.0
[2.275360] Creating 6 MTD partitions on "brcmnand.0":
[2.280804] 0x-0x0002 : "boot"
[2.294609] 0x0004-0x0112 : "rootfs"
[2.310078] 0x07b0-0x07f0 : "data"
[2.324052] 0x0002-0x03ac : "rootfs1_update"
[2.339190] 0x0400-0x07ac : "rootfs2_update"
[2.354290] 0x0402-0x0506 : "rootfs_other"

The nvram contains the offset and size of the boot, rootfs1, rootfs2
and data partitions. The presence of CFE and nvram is already verified
by reading from the boot partition which is assumed to be at offset 0
and the NAND process aborts if the nvram read indicates that this is
not the case.

There is bcm_tag information at the start of each rootfs that is used
to determine which rootfs is newer and what its real offset/size is.

The CFE bootline is used to select a rootfs.

Signed-off-by: Simon Arlott 
---
v4: Reorganised functions based on earlier new patches in the series,
no real logic changes other than having to check for nvram->version
>= 6 within the nand function instead of the nvram read function.

Renamed "curpart" to "i" because it allows the partition layout
lines to be under 80 characters.

v3: Use COMPILE_TEST.

Ensure that strings read from flash are null terminated and validate
bcm_tag integer values (this also moves reporting of rootfs sequence
numbers to later on).

v2: Use external struct bcm963xx_nvram definition for bcm963268part.

Removed support for the nand partition number field, it's not a
standard Broadcom field (was added by MitraStar Technology Corp.).

 drivers/mtd/bcm63xxpart.c | 196 --
 1 file changed, 190 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c
index 26c38a1..4576b78 100644
--- a/drivers/mtd/bcm63xxpart.c
+++ b/drivers/mtd/bcm63xxpart.c
@@ -16,10 +16,9 @@
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
+ * NAND flash layout derived from 
bcm963xx_4.12L.06B_consumer/bcmdrivers/opensource/char/board/bcm963xx/impl1/board.c,
+ * 
bcm963xx_4.12L.06B_consumer/shared/opensource/include/bcm963xx/bcm_hwdefs.h:
+ * Copyright (c) 2002 Broadcom Corporation
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -124,6 +123,25 @@ static int bcm63xx_read_image_tag(struct mtd_info *master, 
const char *name,
return 1;
 }
 
+static bool bcm63xx_boot_latest(struct bcm963xx_nvram *nvram)
+{
+   char *p;
+
+   STR_NULL_TERMINATE(nvram->bootline);
+
+   /* Find previous image parameter "p" */
+   if (!strncmp(nvram->bootline, "p=", 2))
+   p = nvram->bootline;
+   else
+   p = strstr(nvram->bootline, " p=");
+
+   if (p == NULL)
+   return true;
+
+   p += 2;
+   return *p != '0';
+}
+
 static int bcm63xx_parse_cfe_nor_partitions(struct mtd_info *master,
const struct mtd_partition **ppar

[PATCH linux-next v4 10/11] mtd: bcm63xxpart: Move NOR flash layout to a separate function

2015-12-13 Thread Simon Arlott
Move the NOR flash layout to a separate function to allow the NAND flash
layout to be supported.

Signed-off-by: Simon Arlott 
---
v4: New patch.

 drivers/mtd/bcm63xxpart.c | 54 ---
 1 file changed, 32 insertions(+), 22 deletions(-)

diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c
index 41aa202..26c38a1 100644
--- a/drivers/mtd/bcm63xxpart.c
+++ b/drivers/mtd/bcm63xxpart.c
@@ -124,13 +124,11 @@ static int bcm63xx_read_image_tag(struct mtd_info 
*master, const char *name,
return 1;
 }
 
-static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
-   const struct mtd_partition **pparts,
-   struct mtd_part_parser_data *data)
+static int bcm63xx_parse_cfe_nor_partitions(struct mtd_info *master,
+   const struct mtd_partition **pparts, struct bcm963xx_nvram *nvram)
 {
/* CFE, NVRAM and global Linux are always present */
int nrparts = 3, curpart = 0;
-   struct bcm963xx_nvram *nvram = NULL;
struct bcm_tag *buf = NULL;
struct mtd_partition *parts;
int ret;
@@ -141,17 +139,6 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info 
*master,
int i;
bool rootfs_first = false;
 
-   if (bcm63xx_detect_cfe(master))
-   return -EINVAL;
-
-   nvram = vzalloc(sizeof(*nvram));
-   if (!nvram)
-   return -ENOMEM;
-
-   ret = bcm63xx_read_nvram(master, nvram);
-   if (ret)
-   goto out;
-
cfe_erasesize = max_t(uint32_t, master->erasesize,
  BCM963XX_CFE_BLOCK_SIZE);
 
@@ -159,12 +146,9 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info 
*master,
nvramlen = nvram->psi_size * SZ_1K;
nvramlen = roundup(nvramlen, cfe_erasesize);
 
-   /* Allocate memory for buffer */
buf = vmalloc(sizeof(struct bcm_tag));
-   if (!buf) {
-   ret = -ENOMEM;
-   goto out;
-   }
+   if (!buf)
+   return -ENOMEM;
 
/* Get the tag */
ret = bcm63xx_read_image_tag(master, "rootfs", cfelen, buf);
@@ -234,7 +218,6 @@ invalid_tag:
if (kernellen > 0)
nrparts++;
 
-   /* Ask kernel for more memory */
parts = kzalloc(sizeof(*parts) * nrparts + 10 * nrparts, GFP_KERNEL);
if (!parts) {
ret = -ENOMEM;
@@ -292,13 +275,40 @@ invalid_tag:
ret = 0;
 
 out:
-   vfree(nvram);
vfree(buf);
 
if (ret)
return ret;
 
return nrparts;
+}
+
+static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
+   const struct mtd_partition **pparts,
+   struct mtd_part_parser_data *data)
+{
+   struct bcm963xx_nvram *nvram = NULL;
+   int ret;
+
+   if (bcm63xx_detect_cfe(master))
+   return -EINVAL;
+
+   nvram = vzalloc(sizeof(*nvram));
+   if (!nvram)
+   return -ENOMEM;
+
+   ret = bcm63xx_read_nvram(master, nvram);
+   if (ret)
+   goto out;
+
+   if (!mtd_type_is_nand(master))
+   ret = bcm63xx_parse_cfe_nor_partitions(master, pparts, nvram);
+   else
+   ret = -EINVAL;
+
+out:
+   vfree(nvram);
+   return ret;
 };
 
 static struct mtd_part_parser bcm63xx_cfe_parser = {
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH linux-next v4 09/11] mtd: bcm63xxpart: Null terminate and validate conversion of flash strings

2015-12-13 Thread Simon Arlott
Strings read from flash could be missing null termination characters, or
not contain valid integers.

Null terminate the strings and check for errors when converting them to
integers.

Also validate that the addresses are at least BCM963XX_EXTENDED_SIZE
because this will be subtracted from them.

Signed-off-by: Simon Arlott 
---
v4: New patch.

 drivers/mtd/bcm63xxpart.c | 38 ++
 1 file changed, 34 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c
index eafbf52..41aa202 100644
--- a/drivers/mtd/bcm63xxpart.c
+++ b/drivers/mtd/bcm63xxpart.c
@@ -169,10 +169,39 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info 
*master,
/* Get the tag */
ret = bcm63xx_read_image_tag(master, "rootfs", cfelen, buf);
if (!ret) {
-   sscanf(buf->flash_image_start, "%u", &rootfsaddr);
-   sscanf(buf->kernel_address, "%u", &kerneladdr);
-   sscanf(buf->kernel_length, "%u", &kernellen);
-   sscanf(buf->total_length, "%u", &totallen);
+   STR_NULL_TERMINATE(buf->flash_image_start);
+   if (kstrtouint(buf->flash_image_start, 10, &rootfsaddr) ||
+   rootfsaddr < BCM963XX_EXTENDED_SIZE) {
+   pr_err("invalid rootfs address: %*ph\n",
+   sizeof(buf->flash_image_start),
+   buf->flash_image_start);
+   goto invalid_tag;
+   }
+
+   STR_NULL_TERMINATE(buf->kernel_address);
+   if (kstrtouint(buf->kernel_address, 10, &kerneladdr) ||
+   kerneladdr < BCM963XX_EXTENDED_SIZE) {
+   pr_err("invalid kernel address: %*ph\n",
+   sizeof(buf->kernel_address),
+   buf->kernel_address);
+   goto invalid_tag;
+   }
+
+   STR_NULL_TERMINATE(buf->kernel_length);
+   if (kstrtouint(buf->kernel_length, 10, &kernellen)) {
+   pr_err("invalid kernel length: %*ph\n",
+   sizeof(buf->kernel_length),
+   buf->kernel_length);
+   goto invalid_tag;
+   }
+
+   STR_NULL_TERMINATE(buf->total_length);
+   if (kstrtouint(buf->total_length, 10, &totallen)) {
+   pr_err("invalid total length: %*ph\n",
+   sizeof(buf->total_length),
+   buf->total_length);
+   goto invalid_tag;
+   }
 
kerneladdr = kerneladdr - BCM963XX_EXTENDED_SIZE;
rootfsaddr = rootfsaddr - BCM963XX_EXTENDED_SIZE;
@@ -188,6 +217,7 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info 
*master,
rootfslen = spareaddr - rootfsaddr;
}
} else if (ret > 0) {
+invalid_tag:
kernellen = 0;
rootfslen = 0;
rootfsaddr = 0;
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH linux-next v4 08/11] mtd: bcm63xxpart: Extract read of image tag to separate function

2015-12-13 Thread Simon Arlott
Extract image tag reading and CRC check to a separate function.

Signed-off-by: Simon Arlott 
---
v4: New patch.

 drivers/mtd/bcm63xxpart.c | 62 ++-
 1 file changed, 40 insertions(+), 22 deletions(-)

diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c
index 1eea8b6..eafbf52 100644
--- a/drivers/mtd/bcm63xxpart.c
+++ b/drivers/mtd/bcm63xxpart.c
@@ -41,6 +41,10 @@
 #define BCM963XX_CFE_VERSION_OFFSET0x570
 #define BCM963XX_NVRAM_OFFSET  0x580
 
+/* Ensure strings read from flash structs are null terminated */
+#define STR_NULL_TERMINATE(x) \
+   do { char *_str = (x); _str[sizeof(x) - 1] = 0; } while (0)
+
 static int bcm63xx_detect_cfe(struct mtd_info *master)
 {
char buf[9];
@@ -89,6 +93,37 @@ static int bcm63xx_read_nvram(struct mtd_info *master,
return 0;
 }
 
+static int bcm63xx_read_image_tag(struct mtd_info *master, const char *name,
+   loff_t tag_offset, struct bcm_tag *buf)
+{
+   int ret;
+   size_t retlen;
+   u32 computed_crc;
+
+   ret = mtd_read(master, tag_offset, sizeof(*buf), &retlen, (void *)buf);
+   if (ret)
+   return ret;
+
+   if (retlen != sizeof(*buf))
+   return -EIO;
+
+   computed_crc = crc32_le(IMAGETAG_CRC_START, (u8 *)buf,
+   offsetof(struct bcm_tag, header_crc));
+   if (computed_crc == buf->header_crc) {
+   STR_NULL_TERMINATE(buf->board_id);
+   STR_NULL_TERMINATE(buf->tag_version);
+
+   pr_info("%s: CFE image tag found at 0x%llx with version %s, 
board type %s\n",
+   name, tag_offset, buf->tag_version, buf->board_id);
+
+   return 0;
+   }
+
+   pr_warn("%s: CFE image tag at 0x%llx CRC invalid (expected %08x, actual 
%08x)\n",
+   name, tag_offset, buf->header_crc, computed_crc);
+   return 1;
+}
+
 static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
const struct mtd_partition **pparts,
struct mtd_part_parser_data *data)
@@ -99,13 +134,11 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info 
*master,
struct bcm_tag *buf = NULL;
struct mtd_partition *parts;
int ret;
-   size_t retlen;
unsigned int rootfsaddr, kerneladdr, spareaddr;
unsigned int rootfslen, kernellen, sparelen, totallen;
unsigned int cfelen, nvramlen;
unsigned int cfe_erasesize;
int i;
-   u32 computed_crc;
bool rootfs_first = false;
 
if (bcm63xx_detect_cfe(master))
@@ -134,28 +167,13 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info 
*master,
}
 
/* Get the tag */
-   ret = mtd_read(master, cfelen, sizeof(struct bcm_tag), &retlen,
-  (void *)buf);
-
-   if (retlen != sizeof(struct bcm_tag)) {
-   ret = -EIO;
-   goto out;
-   }
-
-   computed_crc = crc32_le(IMAGETAG_CRC_START, (u8 *)buf,
-   offsetof(struct bcm_tag, header_crc));
-   if (computed_crc == buf->header_crc) {
-   char *boardid = &(buf->board_id[0]);
-   char *tagversion = &(buf->tag_version[0]);
-
+   ret = bcm63xx_read_image_tag(master, "rootfs", cfelen, buf);
+   if (!ret) {
sscanf(buf->flash_image_start, "%u", &rootfsaddr);
sscanf(buf->kernel_address, "%u", &kerneladdr);
sscanf(buf->kernel_length, "%u", &kernellen);
sscanf(buf->total_length, "%u", &totallen);
 
-   pr_info("CFE boot tag found with version %s and board type 
%s\n",
-   tagversion, boardid);
-
kerneladdr = kerneladdr - BCM963XX_EXTENDED_SIZE;
rootfsaddr = rootfsaddr - BCM963XX_EXTENDED_SIZE;
spareaddr = roundup(totallen, master->erasesize) + cfelen;
@@ -169,13 +187,13 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info 
*master,
rootfsaddr = kerneladdr + kernellen;
rootfslen = spareaddr - rootfsaddr;
}
-   } else {
-   pr_warn("CFE boot tag CRC invalid (expected %08x, actual 
%08x)\n",
-   buf->header_crc, computed_crc);
+   } else if (ret > 0) {
kernellen = 0;
rootfslen = 0;
rootfsaddr = 0;
spareaddr = cfelen;
+   } else {
+   goto out;
}
sparelen = master->size - spareaddr - nvramlen;
 
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH linux-next v4 07/11] MIPS: bcm63xx: nvram: Remove unused bcm63xx_nvram_get_psi_size() function

2015-12-13 Thread Simon Arlott
Remove bcm63xx_nvram_get_psi_size() as it now has no users.

Signed-off-by: Simon Arlott 
---
v4: New patch.

 arch/mips/bcm63xx/nvram.c  | 11 ---
 arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h |  2 --
 2 files changed, 13 deletions(-)

diff --git a/arch/mips/bcm63xx/nvram.c b/arch/mips/bcm63xx/nvram.c
index 05757ae..5f2bc1e 100644
--- a/arch/mips/bcm63xx/nvram.c
+++ b/arch/mips/bcm63xx/nvram.c
@@ -19,8 +19,6 @@
 
 #include 
 
-#define BCM63XX_DEFAULT_PSI_SIZE   64
-
 static struct bcm963xx_nvram nvram;
 static int mac_addr_used;
 
@@ -87,12 +85,3 @@ int bcm63xx_nvram_get_mac_address(u8 *mac)
return 0;
 }
 EXPORT_SYMBOL(bcm63xx_nvram_get_mac_address);
-
-int bcm63xx_nvram_get_psi_size(void)
-{
-   if (nvram.psi_size > 0)
-   return nvram.psi_size;
-
-   return BCM63XX_DEFAULT_PSI_SIZE;
-}
-EXPORT_SYMBOL(bcm63xx_nvram_get_psi_size);
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h 
b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
index 348df49..4e0b6bc 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_nvram.h
@@ -30,6 +30,4 @@ u8 *bcm63xx_nvram_get_name(void);
  */
 int bcm63xx_nvram_get_mac_address(u8 *mac);
 
-int bcm63xx_nvram_get_psi_size(void);
-
 #endif /* BCM63XX_NVRAM_H */
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH linux-next v4 06/11] mtd: bcm63xxpart: Remove dependency on mach-bcm63xx

2015-12-13 Thread Simon Arlott
Read nvram directly from flash instead of using the in-memory copy that
mach-bcm63xx has, to remove the dependency on mach-bcm63xx and allow the
parser to work on bmips too.

Rename remaining BCM63XX defines to BCM963XX as these are properties of
the flash layout on the board.

BCM963XX_DEFAULT_PSI_SIZE changes from SZ_64K to 64 because it will be
multiplied by SZ_1K later on.

Signed-off-by: Simon Arlott 
---
v4: New patch.

 drivers/mtd/Kconfig   |  2 +-
 drivers/mtd/bcm63xxpart.c | 72 +--
 2 files changed, 58 insertions(+), 16 deletions(-)

diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 42cc953..e83a279 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -142,7 +142,7 @@ config MTD_AR7_PARTS
 
 config MTD_BCM63XX_PARTS
tristate "BCM63XX CFE partitioning support"
-   depends on BCM63XX
+   depends on BCM63XX || BMIPS_GENERIC || COMPILE_TEST
select CRC32
help
  This provides partions parsing for BCM63xx devices with CFE
diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c
index cec3188..1eea8b6 100644
--- a/drivers/mtd/bcm63xxpart.c
+++ b/drivers/mtd/bcm63xxpart.c
@@ -24,6 +24,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include 
 #include 
 #include 
 #include 
@@ -34,12 +35,11 @@
 #include 
 #include 
 
-#include 
-#include 
+#define BCM963XX_CFE_BLOCK_SIZESZ_64K  /* always at least 
64KiB */
 
-#define BCM63XX_CFE_BLOCK_SIZE SZ_64K  /* always at least 64KiB */
-
-#define BCM63XX_CFE_MAGIC_OFFSET 0x4e0
+#define BCM963XX_CFE_MAGIC_OFFSET  0x4e0
+#define BCM963XX_CFE_VERSION_OFFSET0x570
+#define BCM963XX_NVRAM_OFFSET  0x580
 
 static int bcm63xx_detect_cfe(struct mtd_info *master)
 {
@@ -58,20 +58,45 @@ static int bcm63xx_detect_cfe(struct mtd_info *master)
return 0;
 
/* very old CFE's do not have the cfe-v string, so check for magic */
-   ret = mtd_read(master, BCM63XX_CFE_MAGIC_OFFSET, 8, &retlen,
+   ret = mtd_read(master, BCM963XX_CFE_MAGIC_OFFSET, 8, &retlen,
   (void *)buf);
buf[retlen] = 0;
 
return strncmp("CFE1CFE1", buf, 8);
 }
 
+static int bcm63xx_read_nvram(struct mtd_info *master,
+   struct bcm963xx_nvram *nvram)
+{
+   u32 actual_crc, expected_crc;
+   size_t retlen;
+   int ret;
+
+   /* extract nvram data */
+   ret = mtd_read(master, BCM963XX_NVRAM_OFFSET, BCM963XX_NVRAM_V5_SIZE,
+   &retlen, (void *)nvram);
+   if (ret)
+   return ret;
+
+   ret = bcm963xx_nvram_checksum(nvram, &expected_crc, &actual_crc);
+   if (ret)
+   pr_warn("nvram checksum failed, contents may be invalid 
(expected %08x, got %08x)\n",
+   expected_crc, actual_crc);
+
+   if (!nvram->psi_size)
+   nvram->psi_size = BCM963XX_DEFAULT_PSI_SIZE;
+
+   return 0;
+}
+
 static int bcm63xx_parse_cfe_partitions(struct mtd_info *master,
const struct mtd_partition **pparts,
struct mtd_part_parser_data *data)
 {
/* CFE, NVRAM and global Linux are always present */
int nrparts = 3, curpart = 0;
-   struct bcm_tag *buf;
+   struct bcm963xx_nvram *nvram = NULL;
+   struct bcm_tag *buf = NULL;
struct mtd_partition *parts;
int ret;
size_t retlen;
@@ -86,25 +111,35 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info 
*master,
if (bcm63xx_detect_cfe(master))
return -EINVAL;
 
+   nvram = vzalloc(sizeof(*nvram));
+   if (!nvram)
+   return -ENOMEM;
+
+   ret = bcm63xx_read_nvram(master, nvram);
+   if (ret)
+   goto out;
+
cfe_erasesize = max_t(uint32_t, master->erasesize,
- BCM63XX_CFE_BLOCK_SIZE);
+ BCM963XX_CFE_BLOCK_SIZE);
 
cfelen = cfe_erasesize;
-   nvramlen = bcm63xx_nvram_get_psi_size() * SZ_1K;
+   nvramlen = nvram->psi_size * SZ_1K;
nvramlen = roundup(nvramlen, cfe_erasesize);
 
/* Allocate memory for buffer */
buf = vmalloc(sizeof(struct bcm_tag));
-   if (!buf)
-   return -ENOMEM;
+   if (!buf) {
+   ret = -ENOMEM;
+   goto out;
+   }
 
/* Get the tag */
ret = mtd_read(master, cfelen, sizeof(struct bcm_tag), &retlen,
   (void *)buf);
 
if (retlen != sizeof(struct bcm_tag)) {
-   vfree(buf);
-   return -EIO;
+   ret = -EIO;
+   goto out;
}
 
computed_crc = crc32_le(IMAGETAG_CRC_START, (u8 *)buf,
@@ -154,8 +189,8 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info 
*master,
/* Ask kernel for more memo

[PATCH linux-next v4 05/11] MIPS: bcm963xx: Update bcm_tag field image_sequence

2015-12-13 Thread Simon Arlott
The "dual_image" and "inactive_flag" fields should be merged into a single
"image_sequence" field.

Signed-off-by: Simon Arlott 
---
v4: New patch.

 include/linux/bcm963xx_tag.h | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/include/linux/bcm963xx_tag.h b/include/linux/bcm963xx_tag.h
index 08e0133..161c7b3 100644
--- a/include/linux/bcm963xx_tag.h
+++ b/include/linux/bcm963xx_tag.h
@@ -12,8 +12,7 @@
 #define CHIPID_LEN 6   /* Chip Id Length */
 #define IMAGE_LEN  10  /* Length of Length Field */
 #define ADDRESS_LEN12  /* Length of Address field */
-#define DUALFLAG_LEN   2   /* Dual Image flag Length */
-#define INACTIVEFLAG_LEN   2   /* Inactie Flag Length */
+#define IMAGE_SEQUENCE_LEN 4   /* Image sequence Length */
 #define RSASIG_LEN 20  /* Length of RSA Signature in tag */
 #define TAGINFO1_LEN   30  /* Length of vendor information field1 
in tag */
 #define FLASHLAYOUTVER_LEN 4   /* Length of Flash Layout Version 
String tag */
@@ -72,10 +71,10 @@ struct bcm_tag {
char kernel_address[ADDRESS_LEN];
/* 128-137: Size of kernel */
char kernel_length[IMAGE_LEN];
-   /* 138-139: Unused at the moment */
-   char dual_image[DUALFLAG_LEN];
-   /* 140-141: Unused at the moment */
-   char inactive_flag[INACTIVEFLAG_LEN];
+   /* 138-141: Image sequence number
+* (to be incremented when flashed with a new image)
+*/
+   char image_sequence[IMAGE_SEQUENCE_LEN];
/* 142-161: RSA Signature (not used; some vendors may use this) */
char rsa_signature[RSASIG_LEN];
/* 162-191: Compilation and related information (not used in OpenWrt) */
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH linux-next v4 04/11] MIPS: bcm963xx: Move extended flash address to bcm_tag header file

2015-12-13 Thread Simon Arlott
The extended flash address needs to be subtracted from bcm_tag flash
image offsets. Move this value to the bcm_tag header file.

Renamed define name to consistently use bcm963xx for flash layout
which should be considered a property of the board and not the SoC
(i.e. bcm63xx could theoretically be used on a board without CFE
or any flash).

Signed-off-by: Simon Arlott 
---
v4: New patch.

 drivers/mtd/bcm63xxpart.c| 6 ++
 include/linux/bcm963xx_tag.h | 5 +
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/bcm63xxpart.c b/drivers/mtd/bcm63xxpart.c
index b5bad1f..cec3188 100644
--- a/drivers/mtd/bcm63xxpart.c
+++ b/drivers/mtd/bcm63xxpart.c
@@ -37,8 +37,6 @@
 #include 
 #include 
 
-#define BCM63XX_EXTENDED_SIZE  0xBFC0  /* Extended flash address */
-
 #define BCM63XX_CFE_BLOCK_SIZE SZ_64K  /* always at least 64KiB */
 
 #define BCM63XX_CFE_MAGIC_OFFSET 0x4e0
@@ -123,8 +121,8 @@ static int bcm63xx_parse_cfe_partitions(struct mtd_info 
*master,
pr_info("CFE boot tag found with version %s and board type 
%s\n",
tagversion, boardid);
 
-   kerneladdr = kerneladdr - BCM63XX_EXTENDED_SIZE;
-   rootfsaddr = rootfsaddr - BCM63XX_EXTENDED_SIZE;
+   kerneladdr = kerneladdr - BCM963XX_EXTENDED_SIZE;
+   rootfsaddr = rootfsaddr - BCM963XX_EXTENDED_SIZE;
spareaddr = roundup(totallen, master->erasesize) + cfelen;
 
if (rootfsaddr < kerneladdr) {
diff --git a/include/linux/bcm963xx_tag.h b/include/linux/bcm963xx_tag.h
index f389dac..08e0133 100644
--- a/include/linux/bcm963xx_tag.h
+++ b/include/linux/bcm963xx_tag.h
@@ -28,6 +28,11 @@
"DWV-S0", \
 }
 
+/* Extended flash address, needs to be subtracted
+ * from bcm_tag flash image offsets.
+ */
+#define BCM963XX_EXTENDED_SIZE 0xBFC0
+
 /*
  * The broadcom firmware assumes the rootfs starts the image,
  * therefore uses the rootfs start (flash_image_address)
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH linux-next v4 03/11] MIPS: bcm963xx: Move Broadcom BCM963xx image tag data structure

2015-12-13 Thread Simon Arlott
Move Broadcom BCM963xx image tag data structure to include/linux/
so that drivers outside of mach-bcm63xx can use it.

Signed-off-by: Simon Arlott 
---
v4: New patch.

 MAINTAINERS   |  1 +
 arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h | 96 --
 drivers/mtd/bcm63xxpart.c |  2 +-
 include/linux/bcm963xx_tag.h  | 98 +++
 4 files changed, 100 insertions(+), 97 deletions(-)
 delete mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h
 create mode 100644 include/linux/bcm963xx_tag.h

diff --git a/MAINTAINERS b/MAINTAINERS
index ac7de1a..b2ef403 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2392,6 +2392,7 @@ F:arch/mips/boot/dts/brcm/bcm*.dts*
 F: drivers/irqchip/irq-bcm7*
 F: drivers/irqchip/irq-brcmstb*
 F: include/linux/bcm963xx_nvram.h
+F: include/linux/bcm963xx_tag.h
 
 BROADCOM TG3 GIGABIT ETHERNET DRIVER
 M: Prashant Sreedharan 
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h 
b/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h
deleted file mode 100644
index 1e6b587..000
--- a/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h
+++ /dev/null
@@ -1,96 +0,0 @@
-#ifndef __BCM963XX_TAG_H
-#define __BCM963XX_TAG_H
-
-#define TAGVER_LEN 4   /* Length of Tag Version */
-#define TAGLAYOUT_LEN  4   /* Length of FlashLayoutVer */
-#define SIG1_LEN   20  /* Company Signature 1 Length */
-#define SIG2_LEN   14  /* Company Signature 2 Length */
-#define BOARDID_LEN16  /* Length of BoardId */
-#define ENDIANFLAG_LEN 2   /* Endian Flag Length */
-#define CHIPID_LEN 6   /* Chip Id Length */
-#define IMAGE_LEN  10  /* Length of Length Field */
-#define ADDRESS_LEN12  /* Length of Address field */
-#define DUALFLAG_LEN   2   /* Dual Image flag Length */
-#define INACTIVEFLAG_LEN   2   /* Inactie Flag Length */
-#define RSASIG_LEN 20  /* Length of RSA Signature in tag */
-#define TAGINFO1_LEN   30  /* Length of vendor information field1 
in tag */
-#define FLASHLAYOUTVER_LEN 4   /* Length of Flash Layout Version 
String tag */
-#define TAGINFO2_LEN   16  /* Length of vendor information field2 
in tag */
-#define ALTTAGINFO_LEN 54  /* Alternate length for vendor 
information; Pirelli */
-
-#define NUM_PIRELLI2
-#define IMAGETAG_CRC_START 0x
-
-#define PIRELLI_BOARDS { \
-   "AGPF-S0", \
-   "DWV-S0", \
-}
-
-/*
- * The broadcom firmware assumes the rootfs starts the image,
- * therefore uses the rootfs start (flash_image_address)
- * to determine where to flash the image.  Since we have the kernel first
- * we have to give it the kernel address, but the crc uses the length
- * associated with this address (root_length), which is added to the kernel
- * length (kernel_length) to determine the length of image to flash and thus
- * needs to be rootfs + deadcode (jffs2 EOF marker)
-*/
-
-struct bcm_tag {
-   /* 0-3: Version of the image tag */
-   char tag_version[TAGVER_LEN];
-   /* 4-23: Company Line 1 */
-   char sig_1[SIG1_LEN];
-   /*  24-37: Company Line 2 */
-   char sig_2[SIG2_LEN];
-   /* 38-43: Chip this image is for */
-   char chip_id[CHIPID_LEN];
-   /* 44-59: Board name */
-   char board_id[BOARDID_LEN];
-   /* 60-61: Map endianness -- 1 BE 0 LE */
-   char big_endian[ENDIANFLAG_LEN];
-   /* 62-71: Total length of image */
-   char total_length[IMAGE_LEN];
-   /* 72-83: Address in memory of CFE */
-   char cfe__address[ADDRESS_LEN];
-   /* 84-93: Size of CFE */
-   char cfe_length[IMAGE_LEN];
-   /* 94-105: Address in memory of image start
-* (kernel for OpenWRT, rootfs for stock firmware)
-*/
-   char flash_image_start[ADDRESS_LEN];
-   /* 106-115: Size of rootfs */
-   char root_length[IMAGE_LEN];
-   /* 116-127: Address in memory of kernel */
-   char kernel_address[ADDRESS_LEN];
-   /* 128-137: Size of kernel */
-   char kernel_length[IMAGE_LEN];
-   /* 138-139: Unused at the moment */
-   char dual_image[DUALFLAG_LEN];
-   /* 140-141: Unused at the moment */
-   char inactive_flag[INACTIVEFLAG_LEN];
-   /* 142-161: RSA Signature (not used; some vendors may use this) */
-   char rsa_signature[RSASIG_LEN];
-   /* 162-191: Compilation and related information (not used in OpenWrt) */
-   char information1[TAGINFO1_LEN];
-   /* 192-195: Version flash layout */
-   char flash_layout_ver[FLASHLAYOUTVER_LEN];
-   /* 196-199: kernel+rootfs CRC32 */
-   __u32 fskernel_crc;
-   /* 200-215: Unused except on Alice Gate where is is information */
-   char information2[TAGINFO2_LEN];
-   /* 216-219: CRC32 of

[PATCH linux-next v4 02/11] MIPS: bcm63xx: nvram: Use nvram structure definition from header file

2015-12-13 Thread Simon Arlott
Use the common definition of the nvram structure from the header file
include/linux/bcm963xx_nvram.h instead of maintaining a separate copy.

Read the version 5 size of nvram data from memory and then call the
new checksum verification function from the header file.

Signed-off-by: Simon Arlott 
---
v4: Use checksum verification function from header file.

v3: No changes (reworded commit message).

v2: Use external struct bcm963xx_nvram definition for bcm963268part.

 arch/mips/bcm63xx/nvram.c | 35 +++
 1 file changed, 3 insertions(+), 32 deletions(-)

diff --git a/arch/mips/bcm63xx/nvram.c b/arch/mips/bcm63xx/nvram.c
index 4b50d40..05757ae 100644
--- a/arch/mips/bcm63xx/nvram.c
+++ b/arch/mips/bcm63xx/nvram.c
@@ -10,6 +10,7 @@
 
 #define pr_fmt(fmt) "bcm63xx_nvram: " fmt
 
+#include 
 #include 
 #include 
 #include 
@@ -18,23 +19,6 @@
 
 #include 
 
-/*
- * nvram structure
- */
-struct bcm963xx_nvram {
-   u32 version;
-   u8  reserved1[256];
-   u8  name[16];
-   u32 main_tp_number;
-   u32 psi_size;
-   u32 mac_addr_count;
-   u8  mac_addr_base[ETH_ALEN];
-   u8  reserved2[2];
-   u32 checksum_old;
-   u8  reserved3[720];
-   u32 checksum_high;
-};
-
 #define BCM63XX_DEFAULT_PSI_SIZE   64
 
 static struct bcm963xx_nvram nvram;
@@ -42,27 +26,14 @@ static int mac_addr_used;
 
 void __init bcm63xx_nvram_init(void *addr)
 {
-   unsigned int check_len;
u32 crc, expected_crc;
u8 hcs_mac_addr[ETH_ALEN] = { 0x00, 0x10, 0x18, 0xff, 0xff, 0xff };
 
/* extract nvram data */
-   memcpy(&nvram, addr, sizeof(nvram));
+   memcpy(&nvram, addr, BCM963XX_NVRAM_V5_SIZE);
 
/* check checksum before using data */
-   if (nvram.version <= 4) {
-   check_len = offsetof(struct bcm963xx_nvram, reserved3);
-   expected_crc = nvram.checksum_old;
-   nvram.checksum_old = 0;
-   } else {
-   check_len = sizeof(nvram);
-   expected_crc = nvram.checksum_high;
-   nvram.checksum_high = 0;
-   }
-
-   crc = crc32_le(~0, (u8 *)&nvram, check_len);
-
-   if (crc != expected_crc)
+   if (bcm963xx_nvram_checksum(&nvram, &expected_crc, &crc))
pr_warn("nvram checksum failed, contents may be invalid 
(expected %08x, got %08x)\n",
    expected_crc, crc);
 
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH linux-next v4 01/11] MIPS: bcm963xx: Add Broadcom BCM963xx board nvram data structure

2015-12-13 Thread Simon Arlott
Broadcom BCM963xx boards have multiple nvram variants across different
SoCs with additional checksum fields added whenever the size of the
nvram was extended.

Add this structure as a header file so that multiple drivers can use it.

Signed-off-by: Simon Arlott 
---
v4: Move out of uapi.

Add nand offset/size functions/macros.

Add checksum calculation function.

v3: Fix includes/type names, add comments explaining the nvram struct.

v2: Use external struct bcm963xx_nvram definition for bcm963268part.

 MAINTAINERS|   1 +
 include/linux/bcm963xx_nvram.h | 112 +
 2 files changed, 113 insertions(+)
 create mode 100644 include/linux/bcm963xx_nvram.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 31fc0bf..ac7de1a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2391,6 +2391,7 @@ F:arch/mips/kernel/*bmips*
 F: arch/mips/boot/dts/brcm/bcm*.dts*
 F: drivers/irqchip/irq-bcm7*
 F: drivers/irqchip/irq-brcmstb*
+F: include/linux/bcm963xx_nvram.h
 
 BROADCOM TG3 GIGABIT ETHERNET DRIVER
 M: Prashant Sreedharan 
diff --git a/include/linux/bcm963xx_nvram.h b/include/linux/bcm963xx_nvram.h
new file mode 100644
index 000..290c231
--- /dev/null
+++ b/include/linux/bcm963xx_nvram.h
@@ -0,0 +1,112 @@
+#ifndef __LINUX_BCM963XX_NVRAM_H__
+#define __LINUX_BCM963XX_NVRAM_H__
+
+#include 
+#include 
+#include 
+#include 
+
+/*
+ * Broadcom BCM963xx SoC board nvram data structure.
+ *
+ * The nvram structure varies in size depending on the SoC board version. Use
+ * the appropriate minimum BCM963XX_NVRAM_*_SIZE define for the information
+ * you need instead of sizeof(struct bcm963xx_nvram) as this may change.
+ */
+
+#define BCM963XX_NVRAM_V4_SIZE 300
+#define BCM963XX_NVRAM_V5_SIZE (1 * SZ_1K)
+
+#define BCM963XX_DEFAULT_PSI_SIZE  64
+
+enum bcm963xx_nvram_nand_part {
+   BCM963XX_NVRAM_NAND_PART_BOOT = 0,
+   BCM963XX_NVRAM_NAND_PART_ROOTFS_1,
+   BCM963XX_NVRAM_NAND_PART_ROOTFS_2,
+   BCM963XX_NVRAM_NAND_PART_DATA,
+   BCM963XX_NVRAM_NAND_PART_BBT,
+
+   __BCM963XX_NVRAM_NAND_NR_PARTS
+};
+
+struct bcm963xx_nvram {
+   u32 version;
+   charbootline[256];
+   charname[16];
+   u32 main_tp_number;
+   u32 psi_size;
+   u32 mac_addr_count;
+   u8  mac_addr_base[ETH_ALEN];
+   u8  __reserved1[2];
+   u32 checksum_v4;
+
+   u8  __reserved2[292];
+   u32 nand_part_offset[__BCM963XX_NVRAM_NAND_NR_PARTS];
+   u32 nand_part_size[__BCM963XX_NVRAM_NAND_NR_PARTS];
+   u8  __reserved3[388];
+   u32 checksum_v5;
+};
+
+#define BCM963XX_NVRAM_NAND_PART_OFFSET(nvram, part) \
+   bcm963xx_nvram_nand_part_offset(nvram, BCM963XX_NVRAM_NAND_PART_ ##part)
+
+static inline u64 __pure bcm963xx_nvram_nand_part_offset(
+   const struct bcm963xx_nvram *nvram,
+   enum bcm963xx_nvram_nand_part part)
+{
+   return nvram->nand_part_offset[part] * SZ_1K;
+}
+
+#define BCM963XX_NVRAM_NAND_PART_SIZE(nvram, part) \
+   bcm963xx_nvram_nand_part_size(nvram, BCM963XX_NVRAM_NAND_PART_ ##part)
+
+static inline u64 __pure bcm963xx_nvram_nand_part_size(
+   const struct bcm963xx_nvram *nvram,
+   enum bcm963xx_nvram_nand_part part)
+{
+   return nvram->nand_part_size[part] * SZ_1K;
+}
+
+/*
+ * bcm963xx_nvram_checksum - Verify nvram checksum
+ *
+ * @nvram: pointer to full size nvram data structure
+ * @expected_out: optional pointer to store expected checksum value
+ * @actual_out: optional pointer to store actual checksum value
+ *
+ * Return: 0 if the checksum is valid, otherwise -EINVAL
+ */
+static int __maybe_unused bcm963xx_nvram_checksum(
+   const struct bcm963xx_nvram *nvram,
+   u32 *expected_out, u32 *actual_out)
+{
+   u32 expected, actual;
+   size_t len;
+
+   if (nvram->version <= 4) {
+   expected = nvram->checksum_v4;
+   len = BCM963XX_NVRAM_V4_SIZE - sizeof(u32);
+   } else {
+   expected = nvram->checksum_v5;
+   len = BCM963XX_NVRAM_V5_SIZE - sizeof(u32);
+   }
+
+   /*
+* Calculate the CRC32 value for the nvram with a checksum value
+* of 0 without modifying or copying the nvram by combining:
+* - The CRC32 of the nvram without the checksum value
+* - The CRC32 of a zero checksum value (which is also 0)
+*/
+   actual = crc32_le_combine(
+   crc32_le(~0, (u8 *)nvram, len), 0, sizeof(u32));
+
+   if (expected_out)
+   *expected_out = expected;
+
+   if (actual_out)
+   *actual_out = actual;
+
+   return expected == actual ? 0 : -EINVAL;
+};
+
+#endif /* __LINUX_BCM963XX_NVRAM_H__ */
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http

Re: [PATCH linux-next v4 00/11] mtd: bcm63xxpart: Add NAND partitioning support

2015-12-13 Thread Simon Arlott
On 13/12/15 22:42, Simon Arlott wrote:
> The BCM963xx NAND flash boards have a different handling of the
> partition layout from the NOR flash boards. For NAND there are offsets
> for the partitions in nvram. Both types of boards use the same CFE
> bootloader, nvram format and image tag in their rootfs partitions.
> 
> This patch series:
> 1-4:  Creates separate header files for bcm963xx_nvram and bcm_tag structures
> 5:Updates the bcm_tag field image_sequence
> 6:Removes the dependency on mach-bcm63xx from the bcm63xxpart parser
> 7:Removes unused mach-bcm63xx nvram function
> 8-10: Cleanup and move NOR flash layout to a separate function
> 11:   Add NAND flash layout support

These patches are also available on github against next-20151211:
https://github.com/lp0/linux/commits/20151213-bcm63xxpart-v4

(Yes I am aware that the summary line and description of the patches are
not suitable for merging.)

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH linux-next v4 00/11] mtd: bcm63xxpart: Add NAND partitioning support

2015-12-13 Thread Simon Arlott
The BCM963xx NAND flash boards have a different handling of the
partition layout from the NOR flash boards. For NAND there are offsets
for the partitions in nvram. Both types of boards use the same CFE
bootloader, nvram format and image tag in their rootfs partitions.

This patch series:
1-4:  Creates separate header files for bcm963xx_nvram and bcm_tag structures
5:Updates the bcm_tag field image_sequence
6:Removes the dependency on mach-bcm63xx from the bcm63xxpart parser
7:Removes unused mach-bcm63xx nvram function
8-10: Cleanup and move NOR flash layout to a separate function
11:   Add NAND flash layout support

Patches 1-2 tested on BCM63XX with a BCM963168 (NAND) board.
Patches 3-11 compile tested on BCM63XX.
Patches 6-11 tested on BMIPS with a BCM963168 (NAND) board.
---
v4: Move struct bcm_tag to include/linux/.

Modify bcm63xx parser to read nvram from NOR flash and handle the
NAND flash layout in the same parser.

v3: Fix includes/type names, add comments explaining the nvram struct.

Use COMPILE_TEST.

Ensure that strings read from flash are null terminated and validate
bcm_tag integer values (this also moves reporting of rootfs sequence
numbers to later on).

v2: Use external struct bcm963xx_nvram definition for bcm963268part.

Removed support for the nand partition number field, it's not a
standard Broadcom field (was added by MitraStar Technology Corp.).

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH linux-next (v3) 3/3] mtd: part: Add BCM962368 CFE partitioning support

2015-12-13 Thread Simon Arlott
On 11/12/15 23:12, Jonas Gorski wrote:
> On Fri, Dec 11, 2015 at 11:02 PM, Simon Arlott  wrote:
>> +#define BCM63XX_CFE_MAGIC_OFFSET   0x4e0
>> +#define BCM963XX_CFE_VERSION_OFFSET0x570
>> +#define BCM963XX_NVRAM_OFFSET  0x580
> 
> You should decide whether you want to call it BCM63XX (the SoC) or
> BCM963XX (the Board using the SoC). Also probably better served in
> bcm963xx_nvram.h

I'm going to name the CFE locations, nvram and anything that is a
property of the flash layout BCM963XX_*, as a theoretical board using
BCM63XX with no flash wouldn't use these. The parser is still called
bcm63xxpart so that's currently an anomaly.

I'm working on making it support both NOR and NAND flash layouts.

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH linux-next (v3) 1/3] MIPS: bcm963xx: Add Broadcom BCM963xx board nvram data structure

2015-12-12 Thread Simon Arlott
On 11/12/15 23:29, Jonas Gorski wrote:
> On Fri, Dec 11, 2015 at 11:24 PM, Simon Arlott  wrote:
>> On 11/12/15 22:02, Jonas Gorski wrote:
>>> On Fri, Dec 11, 2015 at 10:54 PM, Simon Arlott  wrote:
>>>> Broadcom BCM963xx boards have multiple nvram variants across different
>>>> SoCs with additional checksum fields added whenever the size of the
>>>> nvram was extended.
>>>>
>>>> Add this structure as a header file so that multiple drivers and userspace
>>>> can use it.
>>>>
>>>> Signed-off-by: Simon Arlott 
>>>> ---
>>>> v3: Fix includes/type names, add comments explaining the nvram struct.
>>>>
>>>> v2: Use external struct bcm963xx_nvram definition for bcm963268part.
...
>>>> diff --git a/include/uapi/linux/bcm963xx_nvram.h 
>>>> b/include/uapi/linux/bcm963xx_nvram.h
>>>> new file mode 100644
>>>> index 000..2dcb307
>>>> --- /dev/null
>>>> +++ b/include/uapi/linux/bcm963xx_nvram.h
>>>
>>> Why uapi? The nvram layout isn't really enforced to be that way, and
>>> at least Huawei uses a modified one on some devices (in case you
>>> wondered why bcm63xx doesn't fail a crc32-"broken" one), so IMHO it
>>> should be kept for in-kernel use only.
>>
>> Because Florian suggested include/uapi/linux/bcm963xx_nvram.h; I could
>> move it to include/linux/ instead if this is preferred.
...
>>>> + * Do not use the __reserved fields, especially not as an offset for CRC
>>>> + * calculations (use BCM963XX_NVRAM_*_SIZE instead). These may be removed 
>>>> or
>>>> + * repositioned.
> 
> Because I just saw that: Nobody will read that. ;p

I'll move this to include/linux/bcm963xx_nvram.h and omit the linux-api
mailing list when I next send the patch series.

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH linux-next (v3) 1/3] MIPS: bcm963xx: Add Broadcom BCM963xx board nvram data structure

2015-12-11 Thread Simon Arlott
On 11/12/15 22:02, Jonas Gorski wrote:
> Hi,
> 
> On Fri, Dec 11, 2015 at 10:54 PM, Simon Arlott  wrote:
>> Broadcom BCM963xx boards have multiple nvram variants across different
>> SoCs with additional checksum fields added whenever the size of the
>> nvram was extended.
>>
>> Add this structure as a header file so that multiple drivers and userspace
>> can use it.
>>
>> Signed-off-by: Simon Arlott 
>> ---
>> v3: Fix includes/type names, add comments explaining the nvram struct.
>>
>> v2: Use external struct bcm963xx_nvram definition for bcm963268part.
>>
>>  MAINTAINERS |  1 +
>>  include/uapi/linux/bcm963xx_nvram.h | 53 
>> +
>>  2 files changed, 54 insertions(+)
>>  create mode 100644 include/uapi/linux/bcm963xx_nvram.h
>>
>> diff --git a/MAINTAINERS b/MAINTAINERS
>> index 6b6d4e2e..abf18b4 100644
>> --- a/MAINTAINERS
>> +++ b/MAINTAINERS
>> @@ -2393,6 +2393,7 @@ F:drivers/irqchip/irq-bcm63*
>>  F: drivers/irqchip/irq-bcm7*
>>  F: drivers/irqchip/irq-brcmstb*
>>  F: include/linux/bcm63xx_wdt.h
>> +F: include/uapi/linux/bcm963xx_nvram.h
>>
>>  BROADCOM TG3 GIGABIT ETHERNET DRIVER
>>  M: Prashant Sreedharan 
>> diff --git a/include/uapi/linux/bcm963xx_nvram.h 
>> b/include/uapi/linux/bcm963xx_nvram.h
>> new file mode 100644
>> index 000..2dcb307
>> --- /dev/null
>> +++ b/include/uapi/linux/bcm963xx_nvram.h
> 
> Why uapi? The nvram layout isn't really enforced to be that way, and
> at least Huawei uses a modified one on some devices (in case you
> wondered why bcm63xx doesn't fail a crc32-"broken" one), so IMHO it
> should be kept for in-kernel use only.

Because Florian suggested include/uapi/linux/bcm963xx_nvram.h; I could
move it to include/linux/ instead if this is preferred.

>> @@ -0,0 +1,53 @@
>> +#ifndef _UAPI__LINUX_BCM963XX_NVRAM_H__
>> +#define _UAPI__LINUX_BCM963XX_NVRAM_H__
>> +
>> +#include 
>> +#include 
>> +
>> +/*
>> + * Broadcom BCM963xx SoC board nvram data structure.
>> + *
>> + * The nvram structure varies in size depending on the SoC board version. 
>> Use
>> + * the appropriate minimum BCM963XX_NVRAM_*_SIZE define for the information
>> + * you need instead of sizeof(struct bcm963xx_nvram) as this may change.
>> + *
>> + * The "version" field value maps directly to the size and checksum names, 
>> e.g.
>> + * version 4 uses "checksum_v4" and the data is BCM963XX_NVRAM_V4_SIZE 
>> bytes.
>> + *
>> + * Do not use the __reserved fields, especially not as an offset for CRC
>> + * calculations (use BCM963XX_NVRAM_*_SIZE instead). These may be removed or
>> + * repositioned.
>> + */
>> +
>> +#define BCM963XX_NVRAM_V4_SIZE 300
>> +#define BCM963XX_NVRAM_V5_SIZE 1024
>> +#define BCM963XX_NVRAM_V6_SIZE BCM963XX_NVRAM_V5_SIZE
>> +#define BCM963XX_NVRAM_V7_SIZE 3072
>> +
>> +#define BCM963XX_NVRAM_NR_PARTS5
>> +
>> +struct bcm963xx_nvram {
>> +   __u32   version;
>> +   charbootline[256];
>> +   charname[16];
>> +   __u32   main_tp_number;
>> +   __u32   psi_size;
>> +   __u32   mac_addr_count;
>> +   __u8mac_addr_base[ETH_ALEN];
>> +   __u8__reserved1[2];
>> +   __u32   checksum_v4;
>> +
>> +   __u8__reserved2[292];
>> +   __u32   nand_part_offset[BCM963XX_NVRAM_NR_PARTS];
>> +   __u32   nand_part_size[BCM963XX_NVRAM_NR_PARTS];
>> +   __u8__reserved3[388];
>> +   union {
>> +   __u32   checksum_v5;
>> +   __u32   checksum_v6;
>> +   };
> 
> what's the point of this union? Both are the same size and have the
> same function.

For convenience when deciding which size of nvram to use.

The mach-bcm63xx code uses the V5 definitions because it supports
checksums at the v4 and v5 sizes.

The bcm963xxpart code uses the V6 definitions because that's what my
board has and I can't tell if the nand_part values are valid in version
5 or if they were only added in version 6.
 
>> +
>> +   __u8__reserved4[2044];
>> +   __u32   checksum_v7;
>> +} __packed;
> 
> Why is it __packed? there are no unaligned members, so it should work
> fine without this (and it did for bcm63xx).

I could remove it, but as soon as someone adds an unaligned member but
forgets to add __packed it's going to break.

There are unaligned members in some of the __reserved areas, like this
one:

#define NVRAM_GPON_SERIAL_NUMBER_LEN13
#define NVRAM_GPON_PASSWORD_LEN 11

char gponSerialNumber[NVRAM_GPON_SERIAL_NUMBER_LEN];
char gponPassword[NVRAM_GPON_PASSWORD_LEN];

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH linux-next (v3) 3/3] mtd: part: Add BCM962368 CFE partitioning support

2015-12-11 Thread Simon Arlott
Add partitioning support for BCM963268 boards with CFE bootloaders.
The following partitions are defined:
  "boot":   CFE and nvram data
  "rootfs": Currently selected rootfs
  "data":   Configuration data
  "rootfs1_update": Container for the whole flash area used
for the first rootfs to allow it to be
updated.
  "rootfs2_update": Container for the whole flash area used
for the second rootfs to allow it to be
updated.
  "rootfs_other":   The other (not currently selected) rootfs

Example:
[1.904302] nand: device found, Manufacturer ID: 0xc2, Chip ID: 0xf1
[1.911000] nand: Macronix NAND 128MiB 3,3V 8-bit
[1.915855] nand: 128 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB 
size: 64
[1.923797] bcm6368_nand 1200.nand: detected 128MiB total, 128KiB 
blocks, 2KiB pages, 16B OOB, 8-bit, Hamming ECC
[1.936994] Bad block table found at page 65472, version 0x01
[1.944121] Bad block table found at page 65408, version 0x01
[1.951166] nand_read_bbt: bad block at 0x0748
[1.969377] bcm963268part: rootfs1: CFE boot tag found at 0x2 with 
version 6, board type 963168VX
[1.980690] bcm963268part: rootfs2: CFE boot tag found at 0x400 with 
version 6, board type 963168VX
[1.990801] bcm963268part: CFE bootline selected latest image rootfs1 
(rootfs1_seq=2, rootfs2_seq=1)
[2.022080] 6 bcm963268part partitions found on MTD device brcmnand.0
[2.042659] Creating 6 MTD partitions on "brcmnand.0":
[2.048025] 0x-0x0002 : "boot"
[2.062134] 0x0004-0x0112 : "rootfs"
[2.077632] 0x07b0-0x07f0 : "data"
[2.091363] 0x0002-0x03ac : "rootfs1_update"
[2.106228] 0x0400-0x07ac : "rootfs2_update"
[2.121093] 0x0402-0x0506 : "rootfs_other"

The nvram contains the offset and size of the boot, rootfs1, rootfs2
and data partitions. The presence of CFE and nvram is verified by
reading from the boot partition which is assumed to be at offset 0
and the process aborts if the nvram read indicates that this is not
the case.

There is bcm_tag information at the start of each rootfs that is used
to determine which rootfs is newer and what its real offset/size is.

The CFE bootline is used to select a rootfs.

Signed-off-by: Simon Arlott 
---
v3: Use COMPILE_TEST.

Ensure that strings read from flash are null terminated and validate
bcm_tag integer values (this also moves reporting of rootfs sequence
numbers to later on).

v2: Use external struct bcm963xx_nvram definition for bcm963268part.

Removed support for the nand partition number field, it's not a
standard Broadcom field (was added by MitraStar Technology Corp.).

 drivers/mtd/Kconfig |  21 +++
 drivers/mtd/Makefile|   1 +
 drivers/mtd/bcm963268part.c | 350 
 3 files changed, 372 insertions(+)
 create mode 100644 drivers/mtd/bcm963268part.c

diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 42cc953..8209730 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -148,6 +148,27 @@ config MTD_BCM63XX_PARTS
  This provides partions parsing for BCM63xx devices with CFE
  bootloaders.
 
+config MTD_BCM963268_PARTS
+   tristate "BCM963268 CFE partitioning support"
+   depends on BMIPS_GENERIC || COMPILE_TEST
+   select CRC32
+   help
+ This provides partitions parsing for BCM963268 boards with CFE
+ bootloaders. The following partitions are defined:
+   "boot":   CFE and nvram data
+   "rootfs": Currently selected rootfs
+   "data":   Configuration data
+   "rootfs1_update": Container for the whole flash area used
+ for the first rootfs to allow it to be
+ updated.
+   "rootfs2_update": Container for the whole flash area used
+ for the second rootfs to allow it to be
+ updated.
+   "rootfs_other":   The other (not currently selected) rootfs
+
+ A decision is made regarding which of the two rootfs is to be
+ used based on the nvram data.
+
 config MTD_BCM47XX_PARTS
tristate "BCM47XX partitioning support"
depends on BCM47XX || ARCH_BCM_5301X
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 99bb9a1..f0f4140 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
 obj-$(CONFIG_MTD_AFS_PARTS)+= afs.o
 obj-$(CONFIG_MTD_AR7_PARTS)+= ar7part.o
 obj-$(CONFIG_MTD_BC

[PATCH linux-next (v3) 2/3] MIPS: bcm63xx: nvram: Use nvram structure definition from header file

2015-12-11 Thread Simon Arlott
Use the common definition of the nvram structure from the header file
include/uapi/linux/bcm963xx_nvram.h instead of maintaining a separate
copy.

Read the version 5 size of nvram data from memory and then support the
version 4 and version 5 variants of nvram data checksums.

Signed-off-by: Simon Arlott 
---
Compile tested only (there is no support for brcmnand on mach-bcm63xx).

v3: No changes (reworded commit message).

v2: Use external struct bcm963xx_nvram definition for bcm963268part.

 arch/mips/bcm63xx/nvram.c | 32 
 1 file changed, 8 insertions(+), 24 deletions(-)

diff --git a/arch/mips/bcm63xx/nvram.c b/arch/mips/bcm63xx/nvram.c
index 4b50d40..36e74f9 100644
--- a/arch/mips/bcm63xx/nvram.c
+++ b/arch/mips/bcm63xx/nvram.c
@@ -16,25 +16,9 @@
 #include 
 #include 
 
+#include 
 #include 
 
-/*
- * nvram structure
- */
-struct bcm963xx_nvram {
-   u32 version;
-   u8  reserved1[256];
-   u8  name[16];
-   u32 main_tp_number;
-   u32 psi_size;
-   u32 mac_addr_count;
-   u8  mac_addr_base[ETH_ALEN];
-   u8  reserved2[2];
-   u32 checksum_old;
-   u8  reserved3[720];
-   u32 checksum_high;
-};
-
 #define BCM63XX_DEFAULT_PSI_SIZE   64
 
 static struct bcm963xx_nvram nvram;
@@ -47,17 +31,17 @@ void __init bcm63xx_nvram_init(void *addr)
u8 hcs_mac_addr[ETH_ALEN] = { 0x00, 0x10, 0x18, 0xff, 0xff, 0xff };
 
/* extract nvram data */
-   memcpy(&nvram, addr, sizeof(nvram));
+   memcpy(&nvram, addr, BCM963XX_NVRAM_V5_SIZE);
 
/* check checksum before using data */
if (nvram.version <= 4) {
-   check_len = offsetof(struct bcm963xx_nvram, reserved3);
-   expected_crc = nvram.checksum_old;
-   nvram.checksum_old = 0;
+   check_len = BCM963XX_NVRAM_V4_SIZE;
+   expected_crc = nvram.checksum_v4;
+   nvram.checksum_v4 = 0;
} else {
-   check_len = sizeof(nvram);
-   expected_crc = nvram.checksum_high;
-   nvram.checksum_high = 0;
+   check_len = BCM963XX_NVRAM_V5_SIZE;
+   expected_crc = nvram.checksum_v5;
+   nvram.checksum_v5 = 0;
}
 
crc = crc32_le(~0, (u8 *)&nvram, check_len);
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH linux-next (v3) 1/3] MIPS: bcm963xx: Add Broadcom BCM963xx board nvram data structure

2015-12-11 Thread Simon Arlott
Broadcom BCM963xx boards have multiple nvram variants across different
SoCs with additional checksum fields added whenever the size of the
nvram was extended.

Add this structure as a header file so that multiple drivers and userspace
can use it.

Signed-off-by: Simon Arlott 
---
v3: Fix includes/type names, add comments explaining the nvram struct.

v2: Use external struct bcm963xx_nvram definition for bcm963268part.

 MAINTAINERS |  1 +
 include/uapi/linux/bcm963xx_nvram.h | 53 +
 2 files changed, 54 insertions(+)
 create mode 100644 include/uapi/linux/bcm963xx_nvram.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 6b6d4e2e..abf18b4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2393,6 +2393,7 @@ F:drivers/irqchip/irq-bcm63*
 F: drivers/irqchip/irq-bcm7*
 F: drivers/irqchip/irq-brcmstb*
 F: include/linux/bcm63xx_wdt.h
+F: include/uapi/linux/bcm963xx_nvram.h
 
 BROADCOM TG3 GIGABIT ETHERNET DRIVER
 M: Prashant Sreedharan 
diff --git a/include/uapi/linux/bcm963xx_nvram.h 
b/include/uapi/linux/bcm963xx_nvram.h
new file mode 100644
index 000..2dcb307
--- /dev/null
+++ b/include/uapi/linux/bcm963xx_nvram.h
@@ -0,0 +1,53 @@
+#ifndef _UAPI__LINUX_BCM963XX_NVRAM_H__
+#define _UAPI__LINUX_BCM963XX_NVRAM_H__
+
+#include 
+#include 
+
+/*
+ * Broadcom BCM963xx SoC board nvram data structure.
+ *
+ * The nvram structure varies in size depending on the SoC board version. Use
+ * the appropriate minimum BCM963XX_NVRAM_*_SIZE define for the information
+ * you need instead of sizeof(struct bcm963xx_nvram) as this may change.
+ *
+ * The "version" field value maps directly to the size and checksum names, e.g.
+ * version 4 uses "checksum_v4" and the data is BCM963XX_NVRAM_V4_SIZE bytes.
+ *
+ * Do not use the __reserved fields, especially not as an offset for CRC
+ * calculations (use BCM963XX_NVRAM_*_SIZE instead). These may be removed or
+ * repositioned.
+ */
+
+#define BCM963XX_NVRAM_V4_SIZE 300
+#define BCM963XX_NVRAM_V5_SIZE 1024
+#define BCM963XX_NVRAM_V6_SIZE BCM963XX_NVRAM_V5_SIZE
+#define BCM963XX_NVRAM_V7_SIZE 3072
+
+#define BCM963XX_NVRAM_NR_PARTS5
+
+struct bcm963xx_nvram {
+   __u32   version;
+   charbootline[256];
+   charname[16];
+   __u32   main_tp_number;
+   __u32   psi_size;
+   __u32   mac_addr_count;
+   __u8mac_addr_base[ETH_ALEN];
+   __u8__reserved1[2];
+   __u32   checksum_v4;
+
+   __u8__reserved2[292];
+   __u32   nand_part_offset[BCM963XX_NVRAM_NR_PARTS];
+   __u32   nand_part_size[BCM963XX_NVRAM_NR_PARTS];
+   __u8__reserved3[388];
+   union {
+   __u32   checksum_v5;
+   __u32   checksum_v6;
+   };
+
+   __u8__reserved4[2044];
+   __u32   checksum_v7;
+} __packed;
+
+#endif /* _UAPI__LINUX_BCM963XX_NVRAM_H__ */
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH linux-next 1/2] power: Add brcm,bcm6358-power-controller device tree binding

2015-12-11 Thread Simon Arlott
On 11/12/15 02:58, Rob Herring wrote:
> On Wed, Dec 09, 2015 at 10:29:35PM +0000, Simon Arlott wrote:
>> The BCM6358 contains power domains controlled with a register. Power
>> domains are indexed by bits in the register. Power domain bits can be
>> interleaved with other status bits and clocks in the same register.
>> 
>> Newer SoCs with dedicated power domain registers are active low.
>> 
>> Signed-off-by: Simon Arlott 
>> ---
>>  .../power/brcm,bcm6358-power-controller.txt| 53 
>> ++
>>  1 file changed, 53 insertions(+)
>>  create mode 100644 
>> Documentation/devicetree/bindings/power/brcm,bcm6358-power-controller.txt
>> 
>> diff --git 
>> a/Documentation/devicetree/bindings/power/brcm,bcm6358-power-controller.txt 
>> b/Documentation/devicetree/bindings/power/brcm,bcm6358-power-controller.txt
>> new file mode 100644
>> index 000..556c323
>> --- /dev/null
>> +++ 
>> b/Documentation/devicetree/bindings/power/brcm,bcm6358-power-controller.txt
>> @@ -0,0 +1,53 @@
>> +Broadcom BCM6358 Power domain controller
>> +
>> +This binding uses the power domain bindings:
>> +Documentation/devicetree/bindings/power/power_domain.txt
>> +
>> +The BCM6358 contains power domains controlled with a register. Power
>> +domains are indexed by bits in the register. Power domain bits can be
>> +interleaved with other status bits and clocks in the same register.
>> +
>> +Newer SoCs with dedicated power domain registers are active low.
>> +
>> +Required properties:
>> +- compatible:   Should be "brcm,bcm-power-controller", 
>> "brcm,bcm6358-power-controller"
>> +- #power-domain-cells:  Should be <1>.
>> +- regmap:   The register map phandle
>> +- offset:   Offset in the register map for the power domain 
>> register (in bytes)
>> +- power-domain-indices: The bits in the register used for power domains.
> 
> You should drop this and make the cell values be the register offsets.

I need to register every power domain in order to get the kernel to turn
off those that are unused. Even if I could enumerate all device tree
devices that reference the power-controller node, not all of them have
bindings to allow them to be specified in the device tree file.

I can't register all 32 bits because that won't work on the BCM6358 that
only has 1 power domain bit in the register and several clock bits. On
the BCM63268 there are power domain bits that have no device that I
don't want the kernel to disable (like the memory controller).

How should I determine which bits to register a power domain for?

misc_iddq_ctrl: power-controller@1000184c {
compatible = "brcm,bcm6358-power-controller";
regmap = <&misc>;
offset = <0x4c>;

mask = <0x1043fff>;

#power-domain-cells = <1>;
};

or

misc_iddq_ctrl: power-controller@1000184c {
compatible = "brcm,bcm6358-power-controller";
regmap = <&misc>;
offset = <0x4c>;

#address-cells = <1>;
#size-cells = <0>;

sar: power-controller@0 {
reg = <0>;
#power-domain-cells = <0>;
};

ipsec: power-controller@1 {
reg = <1>;
#power-domain-cells = <0>;
};

...
};

or something else?

>> +- power-domain-names:   Should be a list of strings of power domain names
>> +indexed by the power domain indices.
> 
> This isn't really needed anyway.

If I remove this then I'll have to use the same node name for each
struct generic_pm_domain "name" field that I register, although these
names don't appear to be exported anywhere.

>> +
>> +Optional properties:
>> +- active-low:   Specify that the bits are active low.
> 
> This should be implied by the compatible property.

Ok, I'll create "brcm,bcm6358-power-controller" that's active high and
"brcm,bcm6328-power-controller" that's active low. This appear to be
the earliest chips that introduced or changed "iddq" register bits.

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH linux-next (v2) 3/3] mtd: part: Add BCM962368 CFE partitioning support

2015-12-10 Thread Simon Arlott
Add partitioning support for BCM963268 boards with CFE bootloaders.
The following partitions are defined:
  "boot":   CFE and nvram data
  "rootfs": Currently selected rootfs
  "data":   Configuration data
  "rootfs1_update": Container for the whole flash area used
for the first rootfs to allow it to be
updated.
  "rootfs2_update": Container for the whole flash area used
for the second rootfs to allow it to be
updated.
  "rootfs_other":   The other (not currently selected) rootfs

Example:
[1.904302] nand: device found, Manufacturer ID: 0xc2, Chip ID: 0xf1
[1.911000] nand: Macronix NAND 128MiB 3,3V 8-bit
[1.915855] nand: 128 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB 
size: 64
[1.923797] bcm6368_nand 1200.nand: detected 128MiB total, 128KiB 
blocks, 2KiB pages, 16B OOB, 8-bit, Hamming ECC
[1.936994] Bad block table found at page 65472, version 0x01
[1.944121] Bad block table found at page 65408, version 0x01
[1.951166] nand_read_bbt: bad block at 0x0748
[1.990043] bcm963268part: rootfs1: CFE boot tag found at 0x2 with 
version 6, board type 963168VX and sequence number 2
[2.003060] bcm963268part: rootfs2: CFE boot tag found at 0x400 with 
version 6, board type 963168VX and sequence number 1
[2.015159] bcm963268part: CFE bootline selected latest image rootfs1
[2.022080] 6 bcm963268part partitions found on MTD device brcmnand.0
[2.042659] Creating 6 MTD partitions on "brcmnand.0":
[2.048025] 0x-0x0002 : "boot"
[2.062134] 0x0004-0x0112 : "rootfs"
[2.077632] 0x07b0-0x07f0 : "data"
[2.091363] 0x0002-0x03ac : "rootfs1_update"
[2.106228] 0x0400-0x07ac : "rootfs2_update"
[2.121093] 0x0402-0x0506 : "rootfs_other"

The nvram contains the offset and size of the boot, rootfs1, rootfs2
and data partitions. The presence of CFE and nvram is verified by
reading from the boot partition which is assumed to be at offset 0
and the process aborts if the nvram read indicates that this is not
the case.

There is bcm_tag information at the start of each rootfs that is used
to determine which rootfs is newer and what its real offset/size is.

The CFE bootline is used to select a rootfs.

Signed-off-by: Simon Arlott 
---
v2: Use external struct bcm963xx_nvram definition for bcm963268part.

Removed support for the nand partition number field, it's not a
standard Broadcom field (was added by MitraStar Technology Corp.).

 drivers/mtd/Kconfig |  21 +++
 drivers/mtd/Makefile|   1 +
 drivers/mtd/bcm963268part.c | 326 
 3 files changed, 348 insertions(+)
 create mode 100644 drivers/mtd/bcm963268part.c

diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 42cc953..63cb2db 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -148,6 +148,27 @@ config MTD_BCM63XX_PARTS
  This provides partions parsing for BCM63xx devices with CFE
  bootloaders.
 
+config MTD_BCM963268_PARTS
+   tristate "BCM963268 CFE partitioning support"
+   depends on BMIPS_GENERIC
+   select CRC32
+   help
+ This provides partitions parsing for BCM963268 boards with CFE
+ bootloaders. The following partitions are defined:
+   "boot":   CFE and nvram data
+   "rootfs": Currently selected rootfs
+   "data":   Configuration data
+   "rootfs1_update": Container for the whole flash area used
+ for the first rootfs to allow it to be
+ updated.
+   "rootfs2_update": Container for the whole flash area used
+ for the second rootfs to allow it to be
+ updated.
+   "rootfs_other":   The other (not currently selected) rootfs
+
+ A decision is made regarding which of the two rootfs is to be
+ used based on the nvram data.
+
 config MTD_BCM47XX_PARTS
tristate "BCM47XX partitioning support"
depends on BCM47XX || ARCH_BCM_5301X
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 99bb9a1..f0f4140 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
 obj-$(CONFIG_MTD_AFS_PARTS)+= afs.o
 obj-$(CONFIG_MTD_AR7_PARTS)+= ar7part.o
 obj-$(CONFIG_MTD_BCM63XX_PARTS)+= bcm63xxpart.o
+obj-$(CONFIG_MTD_BCM963268_PARTS) += bcm963268part.o
 obj-$(CONFIG_MTD_BCM47XX_PARTS)+= bcm47xxpart.o
 
 # 'Users' - code which presents funct

[PATCH linux-next (v2) 2/3] MIPS: bcm63xx: Use common nvram structure definition

2015-12-10 Thread Simon Arlott
Use an external common definition of the nvram structure.

Signed-off-by: Simon Arlott 
---
Compile tested only (there is no support for brcmnand on mach-bcm63xx).

v2: Use external struct bcm963xx_nvram definition for bcm963268part.

 arch/mips/bcm63xx/nvram.c | 32 
 1 file changed, 8 insertions(+), 24 deletions(-)

diff --git a/arch/mips/bcm63xx/nvram.c b/arch/mips/bcm63xx/nvram.c
index 4b50d40..36e74f9 100644
--- a/arch/mips/bcm63xx/nvram.c
+++ b/arch/mips/bcm63xx/nvram.c
@@ -16,25 +16,9 @@
 #include 
 #include 
 
+#include 
 #include 
 
-/*
- * nvram structure
- */
-struct bcm963xx_nvram {
-   u32 version;
-   u8  reserved1[256];
-   u8  name[16];
-   u32 main_tp_number;
-   u32 psi_size;
-   u32 mac_addr_count;
-   u8  mac_addr_base[ETH_ALEN];
-   u8  reserved2[2];
-   u32 checksum_old;
-   u8  reserved3[720];
-   u32 checksum_high;
-};
-
 #define BCM63XX_DEFAULT_PSI_SIZE   64
 
 static struct bcm963xx_nvram nvram;
@@ -47,17 +31,17 @@ void __init bcm63xx_nvram_init(void *addr)
u8 hcs_mac_addr[ETH_ALEN] = { 0x00, 0x10, 0x18, 0xff, 0xff, 0xff };
 
/* extract nvram data */
-   memcpy(&nvram, addr, sizeof(nvram));
+   memcpy(&nvram, addr, BCM963XX_NVRAM_V5_SIZE);
 
/* check checksum before using data */
if (nvram.version <= 4) {
-   check_len = offsetof(struct bcm963xx_nvram, reserved3);
-   expected_crc = nvram.checksum_old;
-   nvram.checksum_old = 0;
+   check_len = BCM963XX_NVRAM_V4_SIZE;
+   expected_crc = nvram.checksum_v4;
+   nvram.checksum_v4 = 0;
} else {
-   check_len = sizeof(nvram);
-   expected_crc = nvram.checksum_high;
-   nvram.checksum_high = 0;
+   check_len = BCM963XX_NVRAM_V5_SIZE;
+   expected_crc = nvram.checksum_v5;
+   nvram.checksum_v5 = 0;
}
 
crc = crc32_le(~0, (u8 *)&nvram, check_len);
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH linux-next (v2) 1/3] MIPS: bcm963xx: Add nvram structure

2015-12-10 Thread Simon Arlott
The BCM963xx has multiple nvram variants across different SoCs with
additional checksum fields added whenever the size of the nvram was
extended.

Signed-off-by: Simon Arlott 
---
v2: Use external struct bcm963xx_nvram definition for bcm963268part.

 MAINTAINERS |  1 +
 include/uapi/linux/bcm963xx_nvram.h | 39 +
 2 files changed, 40 insertions(+)
 create mode 100644 include/uapi/linux/bcm963xx_nvram.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 1354720..5d2272c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2396,6 +2396,7 @@ F:drivers/irqchip/irq-brcmstb*
 F: drivers/power/bcm6358*
 F: drivers/reset/bcm/reset-bcm6345*
 F: include/linux/bcm63xx_wdt.h
+F: include/uapi/linux/bcm963xx_nvram.h
 
 BROADCOM TG3 GIGABIT ETHERNET DRIVER
 M: Prashant Sreedharan 
diff --git a/include/uapi/linux/bcm963xx_nvram.h 
b/include/uapi/linux/bcm963xx_nvram.h
new file mode 100644
index 000..470a4b9
--- /dev/null
+++ b/include/uapi/linux/bcm963xx_nvram.h
@@ -0,0 +1,39 @@
+#ifndef _UAPI__LINUX_BCM963XX_NVRAM_H__
+#define _UAPI__LINUX_BCM963XX_NVRAM_H__
+
+#include 
+#include 
+#include 
+
+#define BCM963XX_NVRAM_V4_SIZE 300
+#define BCM963XX_NVRAM_V5_SIZE (1 * SZ_1K)
+#define BCM963XX_NVRAM_V6_SIZE BCM963XX_NVRAM_V5_SIZE
+#define BCM963XX_NVRAM_V7_SIZE (3 * SZ_1K)
+
+#define BCM963XX_NVRAM_NR_PARTS5
+
+struct bcm963xx_nvram {
+   u32 version;
+   charbootline[256];
+   charname[16];
+   u32 main_tp_number;
+   u32 psi_size;
+   u32 mac_addr_count;
+   u8  mac_addr_base[ETH_ALEN];
+   u8  __reserved1[2];
+   u32 checksum_v4;
+
+   u8  __reserved2[292];
+   u32 nand_part_offset[BCM963XX_NVRAM_NR_PARTS];
+   u32 nand_part_size[BCM963XX_NVRAM_NR_PARTS];
+   u8  __reserved3[388];
+   union {
+   u32 checksum_v5;
+   u32 checksum_v6;
+   };
+
+   u8  __reserved4[2044];
+   u32 checksum_v7;
+} __packed;
+
+#endif /* _UAPI__LINUX_BCM963XX_NVRAM_H__ */
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH linux-next (v2) 2/2] clk: bcm6345: Add BCM6345 gated clock support

2015-12-10 Thread Simon Arlott
The BCM6345 contains clocks gated with a register. Clocks are indexed
by bits in the register and are active high. Most MIPS-based BCM63xx
SoCs have a clock gating set of registers, but some have clock gate bits
interleaved with other status bits and configurable clocks in the same
register.

Enabled by default for BMIPS_GENERIC.

Signed-off-by: Simon Arlott 
---
v2: Resend, no changes.

v1: Renamed from BCM63xx to BCM6345.

 MAINTAINERS   |   1 +
 drivers/clk/bcm/Kconfig   |   9 ++
 drivers/clk/bcm/Makefile  |   1 +
 drivers/clk/bcm/clk-bcm6345.c | 191 ++
 4 files changed, 202 insertions(+)
 create mode 100644 drivers/clk/bcm/clk-bcm6345.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 5ac17b0..9b54ddc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2389,6 +2389,7 @@ F:arch/mips/bmips/*
 F: arch/mips/include/asm/mach-bmips/*
 F: arch/mips/kernel/*bmips*
 F: arch/mips/boot/dts/brcm/bcm*.dts*
+F: drivers/clk/bcm/clk-bcm6345*
 F: drivers/irqchip/irq-bcm63*
 F: drivers/irqchip/irq-bcm7*
 F: drivers/irqchip/irq-brcmstb*
diff --git a/drivers/clk/bcm/Kconfig b/drivers/clk/bcm/Kconfig
index f287845..043353a 100644
--- a/drivers/clk/bcm/Kconfig
+++ b/drivers/clk/bcm/Kconfig
@@ -8,6 +8,15 @@ config CLK_BCM_63XX
  Enable common clock framework support for Broadcom BCM63xx DSL SoCs
  based on the ARM architecture
 
+config CLK_BCM_6345
+   bool "Broadcom BCM6345 clock support"
+   depends on BMIPS_GENERIC || COMPILE_TEST
+   depends on COMMON_CLK
+   default BMIPS_GENERIC
+   help
+ Enable common clock framework support for Broadcom BCM6345 DSL SoCs
+ based on the MIPS architecture
+
 config CLK_BCM_KONA
bool "Broadcom Kona CCU clock support"
depends on ARCH_BCM_MOBILE || COMPILE_TEST
diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile
index 247c267..e2bac43 100644
--- a/drivers/clk/bcm/Makefile
+++ b/drivers/clk/bcm/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_CLK_BCM_63XX) += clk-bcm63xx.o
+obj-$(CONFIG_CLK_BCM_6345) += clk-bcm6345.o
 obj-$(CONFIG_CLK_BCM_KONA) += clk-kona.o
 obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o
 obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o
diff --git a/drivers/clk/bcm/clk-bcm6345.c b/drivers/clk/bcm/clk-bcm6345.c
new file mode 100644
index 000..88a1e7e
--- /dev/null
+++ b/drivers/clk/bcm/clk-bcm6345.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2015 Simon Arlott
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Derived from clk-gate.c:
+ * Copyright (C) 2010-2011 Canonical Ltd 
+ * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd 
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/**
+ * DOC: Basic clock which uses a bit in a regmap to gate and ungate the output
+ *
+ * Traits of this clock:
+ * prepare - clk_(un)prepare only ensures parent is (un)prepared
+ * enable - clk_enable and clk_disable are functional & control gating
+ * rate - inherits rate from parent.  No clk_set_rate support
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+struct clk_bcm6345 {
+   struct clk_hw hw;
+   struct regmap *map;
+   u32 offset;
+   u32 mask;
+};
+
+#define to_clk_bcm6345(_hw) container_of(_hw, struct clk_bcm6345, hw)
+
+static int clk_bcm6345_enable(struct clk_hw *hw)
+{
+   struct clk_bcm6345 *gate = to_clk_bcm6345(hw);
+
+   return regmap_write_bits(gate->map, gate->offset,
+   gate->mask, gate->mask);
+}
+
+static void clk_bcm6345_disable(struct clk_hw *hw)
+{
+   struct clk_bcm6345 *gate = to_clk_bcm6345(hw);
+
+   regmap_write_bits(gate->map, gate->offset,
+   gate->mask, 0);
+}
+
+static int clk_bcm6345_is_enabled(struct clk_hw *hw)
+{
+   struct clk_bcm6345 *gate = to_clk_bcm6345(hw);
+   unsigned int val;
+   int ret;
+
+   ret = regmap_read(gate->map, gate->offset, &val);
+   if (ret)
+   return ret;
+
+   val &= gate->mask;
+
+   return val ? 1 : 0;
+}
+
+const struct clk_ops clk_bcm6345_ops = {
+   .enable = clk_bcm6345_enable,
+   .disable = clk_bcm6345_disable,
+   .is_enabled = clk_bcm6345_is_enabled,
+};
+
+static struct clk * __init of_bcm6345_clk_register(const char *parent_name,
+   const char *clk_name, struct regm

[PATCH linux-next (v2) 1/2] clk: Add brcm,bcm6345-gate-clk device tree binding

2015-12-10 Thread Simon Arlott
Add device tree binding for the BCM6345's gated clocks.

The BCM6345 contains clocks gated with a register. Clocks are indexed
by bits in the register and are active high. Most MIPS-based BCM63xx
SoCs have a clock gating set of registers, but some have clock gate bits
interleaved with other status bits and configurable clocks in the same
register.

Signed-off-by: Simon Arlott 
---
v2: Added clock-indices, clock-output-names (from clock-bindings.txt),
these are required properties.

v1: Renamed from BCM63xx to BCM6345.

 .../bindings/clock/brcm,bcm6345-gate-clk.txt   | 62 ++
 1 file changed, 62 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/clock/brcm,bcm6345-gate-clk.txt

diff --git a/Documentation/devicetree/bindings/clock/brcm,bcm6345-gate-clk.txt 
b/Documentation/devicetree/bindings/clock/brcm,bcm6345-gate-clk.txt
new file mode 100644
index 000..a6e264c
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/brcm,bcm6345-gate-clk.txt
@@ -0,0 +1,62 @@
+Broadcom BCM6345 clocks
+
+This binding uses the common clock binding:
+   Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+The BCM6345 contains clocks gated with a register. Clocks are indexed
+by bits in the register and are active high. Most MIPS-based BCM63xx
+SoCs have a clock gating set of registers, but some have clock gate bits
+interleaved with other status bits and configurable clocks in the same
+register.
+
+Required properties:
+- compatible: Should be "brcm,bcm-gate-clk", 
"brcm,bcm6345-gate-clk"
+- #clock-cells:   Should be <1>.
+- regmap: The register map phandle
+- offset: Offset in the register map for the clock register (in 
bytes)
+- clocks: The external oscillator clock phandle
+- clock-indices:  The bits in the register used for gated clocks.
+- clock-output-names: Should be a list of strings of clock output signal
+  names indexed by the clock indices.
+
+Example:
+
+periph_clk: periph_clk {
+   compatible = "brcm,bcm63168-gate-clk", "brcm,bcm6345-gate-clk";
+   regmap = <&periph_cntl>;
+   offset = <0x4>;
+
+   #clock-cells = <1>;
+   clock-indices =
+   <1>,  <2>,<3>,   <4>, <5>,
+   <6>,  <7>,<8>,   <9>, <10>,
+   <11>, <12>,   <13>,  <14>,<15>,
+   <16>, <17>,   <18>,  <19>,<20>,
+   <27>, <31>;
+   clock-output-names =
+   "vdsl_qproc", "vdsl_afe", "vdsl","mips",  "wlan_ocp",
+   "dect",   "fap0", "fap1","sar",   "robosw",
+   "pcm","usbd", "usbh","ipsec", "spi",
+   "hsspi",  "pcie", "phymips", "gmac",  "nand",
+   "tbus",   "robosw250";
+};
+
+timer_clk: timer_clk {
+   compatible = "brcm,bcm63168-gate-clk", "brcm,bcm6345-gate-clk";
+   regmap = <&timer_cntl>;
+   offset = <0x4>;
+
+   #clock-cells = <1>;
+   clock-indices = <17>, <18>;
+   clock-output-names = "uto_extin", "usb_ref";
+};
+
+ehci0: usb@10002500 {
+   compatible = "brcm,bcm63168-ehci", "brcm,bcm6345-ehci", "generic-ehci";
+   reg = <0x10002500 0x100>;
+   big-endian;
+   interrupt-parent = <&periph_intc>;
+   interrupts = <10>;
+   clocks = <&periph_clk 13>, <&timer_clk 18>;
+   phys = <&usbh>;
+};
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH linux-next (v3) 2/2] reset: bcm6345: Add support for the BCM6345 soft-reset controller

2015-12-10 Thread Simon Arlott
The BCM6345 contains a soft-reset controller activated by setting
a bit (that must previously have been cleared).

Signed-off-by: Simon Arlott 
---
v3: Resend based on linux-next, no changes.

v2: Renamed to bcm6345, removed "mask" property (and the regmap register
size is always assumed to be 32 bits).
Moved from drivers/reset/ to drivers/reset/bcm/.

 MAINTAINERS   |   1 +
 drivers/reset/Kconfig |   1 +
 drivers/reset/Makefile|  17 +++---
 drivers/reset/bcm/Kconfig |  10 
 drivers/reset/bcm/Makefile|   1 +
 drivers/reset/bcm/reset-bcm6345.c | 109 ++
 6 files changed, 131 insertions(+), 8 deletions(-)
 create mode 100644 drivers/reset/bcm/Kconfig
 create mode 100644 drivers/reset/bcm/Makefile
 create mode 100644 drivers/reset/bcm/reset-bcm6345.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 9b54ddc..b81b238 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2393,6 +2393,7 @@ F:drivers/clk/bcm/clk-bcm6345*
 F: drivers/irqchip/irq-bcm63*
 F: drivers/irqchip/irq-bcm7*
 F: drivers/irqchip/irq-brcmstb*
+F: drivers/reset/bcm/reset-bcm6345*
 F: include/linux/bcm63xx_wdt.h
 
 BROADCOM TG3 GIGABIT ETHERNET DRIVER
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 0615f50..ee73f5f 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -12,4 +12,5 @@ menuconfig RESET_CONTROLLER
 
  If unsure, say no.
 
+source "drivers/reset/bcm/Kconfig"
 source "drivers/reset/sti/Kconfig"
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 85d5904..a34f469 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -1,8 +1,9 @@
-obj-$(CONFIG_RESET_CONTROLLER) += core.o
-obj-$(CONFIG_ARCH_LPC18XX) += reset-lpc18xx.o
-obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
-obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
-obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
-obj-$(CONFIG_ARCH_STI) += sti/
-obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o
-obj-$(CONFIG_ATH79) += reset-ath79.o
+obj-$(CONFIG_RESET_CONTROLLER) += core.o
+obj-$(CONFIG_ARCH_LPC18XX) += reset-lpc18xx.o
+obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
+obj-$(CONFIG_ARCH_BERLIN)  += reset-berlin.o
+obj-$(CONFIG_ARCH_SUNXI)   += reset-sunxi.o
+obj-$(CONFIG_ARCH_STI) += sti/
+obj-$(CONFIG_ARCH_ZYNQ)+= reset-zynq.o
+obj-$(CONFIG_ATH79)+= reset-ath79.o
+obj-y  += bcm/
diff --git a/drivers/reset/bcm/Kconfig b/drivers/reset/bcm/Kconfig
new file mode 100644
index 000..85931c9
--- /dev/null
+++ b/drivers/reset/bcm/Kconfig
@@ -0,0 +1,10 @@
+if RESET_CONTROLLER
+
+config RESET_BCM6345
+   bool "BCM6345 Reset Controller"
+   depends on BMIPS_GENERIC
+   default BMIPS_GENERIC
+   help
+ Support resetting of devices on BCM6345 boards.
+
+endif
diff --git a/drivers/reset/bcm/Makefile b/drivers/reset/bcm/Makefile
new file mode 100644
index 000..3d004bd
--- /dev/null
+++ b/drivers/reset/bcm/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_RESET_BCM6345)+= reset-bcm6345.o
diff --git a/drivers/reset/bcm/reset-bcm6345.c 
b/drivers/reset/bcm/reset-bcm6345.c
new file mode 100644
index 000..a95433d
--- /dev/null
+++ b/drivers/reset/bcm/reset-bcm6345.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2015 Simon Arlott
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * Derived from reset-berlin.c:
+ * Copyright (C) 2014 Marvell Technology Group Ltd.
+ *
+ * Antoine Tenart 
+ * Sebastian Hesselbarth 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define to_bcm6345_reset_priv(p) \
+   container_of((p), struct bcm6345_reset_priv, rcdev)
+
+struct bcm6345_reset_priv {
+   struct regmap *map;
+   u32 offset;
+   struct reset_controller_dev rcdev;
+   struct mutex mutex;
+};
+
+static int bcm6345_reset_reset(struct reset_controller_dev *rcdev,
+   unsigned long id)
+{
+   struct bcm6345_reset_priv *priv = to_bcm6345_reset_priv(rcdev);
+
+   mutex_lock(&priv->mutex);
+   regmap_write_bits(priv->map, priv->offset, BIT(id), 0);
+   usleep_range(1, 2);
+   regmap_write_bits(priv->map, priv->offset, BIT(id), BIT(id));
+   usleep_range(1, 2);
+   mutex_unlock(&priv->mutex);
+
+   return 0;
+}
+
+static struct reset_control_ops bcm6345_reset_ops = {
+   .reset = bcm6345_reset_reset,
+};
+
+static int __init bcm6345_reset_probe(struct platform_device *pdev)
+{
+   struct device_node *np = pdev->dev.of_node;
+   struct bcm6345_reset_priv *priv;
+   int ret;
+
+   priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL)

[PATCH linux-next (v3) 1/2] reset: Add brcm,bcm6345-reset device tree binding

2015-12-10 Thread Simon Arlott
Add device tree binding for the BCM6345 soft reset controller.

The BCM6345 contains a soft-reset controller activated by setting
a bit (that must previously have been cleared).

Signed-off-by: Simon Arlott 
---
v3: Resend. Example has changed because usbh now has two compatible
strings and uses a power domain instead of a regulator.

v2: Renamed to bcm6345, removed "mask" property.
Acked-by: Rob Herring 

 .../bindings/reset/brcm,bcm6345-reset.txt  | 33 ++
 1 file changed, 33 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/reset/brcm,bcm6345-reset.txt

diff --git a/Documentation/devicetree/bindings/reset/brcm,bcm6345-reset.txt 
b/Documentation/devicetree/bindings/reset/brcm,bcm6345-reset.txt
new file mode 100644
index 000..0313040
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/brcm,bcm6345-reset.txt
@@ -0,0 +1,33 @@
+Broadcom BCM6345 reset controller
+
+The BCM6345 contains a basic soft reset controller in the perf register
+set which resets components using a bit in a register.
+
+Please also refer to reset.txt in this directory for common reset
+controller binding usage.
+
+Required properties:
+- compatible:  Should be "brcm,bcm-reset", "brcm,bcm6345-reset"
+- regmap:  The register map phandle
+- offset:  Offset in the register map for the reset register (in bytes)
+- #reset-cells:Must be set to 1
+
+Example:
+
+periph_soft_rst: reset-controller {
+   compatible = "brcm,bcm63168-reset", "brcm,bcm6345-reset";
+   regmap = <&periph_cntl>;
+   offset = <0x10>;
+
+   #reset-cells = <1>;
+};
+
+usbh: usbphy@10002700 {
+   compatible = "brcm,bcm63168-usbh", "brcm,bcm6328-usbh";
+   reg = <0x10002700 0x38>;
+   clocks = <&periph_clk 13>, <&timer_clk 18>;
+   resets = <&periph_soft_rst 6>;
+   power-domains = <&misc_iddq_ctrl 4>;
+   #phy-cells = <0>;
+};
+
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH linux-next] mtd: part: Add BCM962368 CFE partitioning support

2015-12-10 Thread Simon Arlott
On 10/12/15 17:41, Florian Fainelli wrote:
> Le 09/12/2015 13:55, Simon Arlott a écrit :
>>  drivers/mtd/Kconfig |  21 +++
>>  drivers/mtd/Makefile|   1 +
>>  drivers/mtd/bcm963268part.c | 373 
>> 
>>  3 files changed, 395 insertions(+)
>>  create mode 100644 drivers/mtd/bcm963268part.c
> 
> What motivated created a separate partition parser rather then using the
> extended the existing one?

I started off doing that but had to split it up because how it handles
the nvram and bcm_tag to construct the partition layout is significantly
different. The nvram isn't even read from flash in bcm63xxpart, and the
psi size value isn't used by bcm963268.

> I would imagine that, at some point, the partition parser could know
> what kind of flash it needs to parse: SPI/P-NOR or NAND, and based on
> that, do an appropriate definition?

With the device tree changes Brian's introducing it can be specified in
there, otherwise a common parser would need to read from the
miscStrapBus register which would be difficult for a partition parser as
it's not a device and has no memory resources.

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH linux-next 2/2] power: bcm6358-power: Add BCM6358 power domain controller support

2015-12-09 Thread Simon Arlott
The BCM6358 contains power domains controlled with a register. Power
domains are indexed by bits in the register. Power domain bits can be
interleaved with other status bits and clocks in the same register.

Newer SoCs with dedicated power domain registers are active low.

Signed-off-by: Simon Arlott 
---
 MAINTAINERS   |   1 +
 drivers/power/Kconfig |  11 +++
 drivers/power/Makefile|   1 +
 drivers/power/bcm6358-power.c | 198 ++
 4 files changed, 211 insertions(+)
 create mode 100644 drivers/power/bcm6358-power.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 0370aba..5546a53 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2391,6 +2391,7 @@ F:drivers/clk/bcm/clk-bcm6345*
 F: drivers/irqchip/irq-bcm63*
 F: drivers/irqchip/irq-bcm7*
 F: drivers/irqchip/irq-brcmstb*
+F: drivers/power/bcm6358*
 F: drivers/reset/bcm/reset-bcm6345*
 F: include/linux/bcm63xx_wdt.h
 
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 1ddd13c..3d6f842 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -506,3 +506,14 @@ endif # POWER_SUPPLY
 
 source "drivers/power/reset/Kconfig"
 source "drivers/power/avs/Kconfig"
+
+config BCM6358_POWER
+   bool "BCM6358 power domain support"
+   depends on BMIPS_GENERIC && PM && OF
+   select PM_GENERIC_DOMAINS
+   select PM_GENERIC_DOMAINS_OF
+   default BMIPS_GENERIC
+   help
+ Say Y here to enable support for power domains on the BCM6358.
+ Required to ensure that power is enabled for SoC peripheral
+ devices, and that power is disabled to unused devices.
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index 0e4eab5..0b72dd2 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -10,6 +10,7 @@ obj-$(CONFIG_GENERIC_ADC_BATTERY) += generic-adc-battery.o
 obj-$(CONFIG_PDA_POWER)+= pda_power.o
 obj-$(CONFIG_APM_POWER)+= apm_power.o
 obj-$(CONFIG_AXP20X_POWER) += axp20x_usb_power.o
+obj-$(CONFIG_BCM6358_POWER)+= bcm6358-power.o
 obj-$(CONFIG_MAX8925_POWER)+= max8925_power.o
 obj-$(CONFIG_WM831X_BACKUP)+= wm831x_backup.o
 obj-$(CONFIG_WM831X_POWER) += wm831x_power.o
diff --git a/drivers/power/bcm6358-power.c b/drivers/power/bcm6358-power.c
new file mode 100644
index 000..f4654d7
--- /dev/null
+++ b/drivers/power/bcm6358-power.c
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2015 Simon Arlott
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define BITS 32
+
+struct bcm6358_power;
+
+struct bcm6358_power_dev {
+   struct generic_pm_domain genpd;
+   struct bcm6358_power *power;
+   u32 bit;
+};
+
+struct bcm6358_power {
+   struct regmap *map;
+   u32 offset;
+   bool active_low;
+
+   struct bcm6358_power_dev dev[BITS];
+   struct genpd_onecell_data genpd_data;
+   struct generic_pm_domain *genpd[BITS];
+};
+
+static int bcm6358_power_get_state(struct bcm6358_power_dev *pmd,
+   bool *is_on)
+{
+   struct bcm6358_power *power = pmd->power;
+   unsigned int val;
+   int ret;
+
+   ret = regmap_read(power->map, power->offset, &val);
+   if (ret) {
+   *is_on = false;
+   return ret;
+   }
+
+   if (power->active_low)
+   *is_on = !(val & pmd->bit);
+   else
+   *is_on = (val & pmd->bit);
+   return 0;
+}
+
+static int bcm6358_power_set_state(struct bcm6358_power_dev *pmd,
+   bool on)
+{
+   struct bcm6358_power *power = pmd->power;
+   u32 val;
+
+   if (power->active_low)
+   val = on ? 0 : pmd->bit;
+   else
+   val = on ? pmd->bit : 0;
+
+   return regmap_update_bits(power->map, power->offset, pmd->bit, val);
+}
+
+static int bcm6358_power_power_on(struct generic_pm_domain *genpd)
+{
+   struct bcm6358_power_dev *pmd = container_of(genpd,
+   struct bcm6358_power_dev, genpd);
+
+   return bcm6358_power_set_state(pmd, true);
+}
+
+static int bcm6358_power_power_off(struct generic_pm_domain *genpd)
+{
+   struct bcm6358_power_dev *pmd = container_of(genpd,
+   struct bcm6358_power_dev, genpd);
+
+   return bcm6358_power_set_state(pmd, false);
+}
+
+static int __init bcm6358_power_probe(struct platfo

[PATCH linux-next 1/2] power: Add brcm,bcm6358-power-controller device tree binding

2015-12-09 Thread Simon Arlott
The BCM6358 contains power domains controlled with a register. Power
domains are indexed by bits in the register. Power domain bits can be
interleaved with other status bits and clocks in the same register.

Newer SoCs with dedicated power domain registers are active low.

Signed-off-by: Simon Arlott 
---
 .../power/brcm,bcm6358-power-controller.txt| 53 ++
 1 file changed, 53 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/power/brcm,bcm6358-power-controller.txt

diff --git 
a/Documentation/devicetree/bindings/power/brcm,bcm6358-power-controller.txt 
b/Documentation/devicetree/bindings/power/brcm,bcm6358-power-controller.txt
new file mode 100644
index 000..556c323
--- /dev/null
+++ b/Documentation/devicetree/bindings/power/brcm,bcm6358-power-controller.txt
@@ -0,0 +1,53 @@
+Broadcom BCM6358 Power domain controller
+
+This binding uses the power domain bindings:
+Documentation/devicetree/bindings/power/power_domain.txt
+
+The BCM6358 contains power domains controlled with a register. Power
+domains are indexed by bits in the register. Power domain bits can be
+interleaved with other status bits and clocks in the same register.
+
+Newer SoCs with dedicated power domain registers are active low.
+
+Required properties:
+- compatible:   Should be "brcm,bcm-power-controller", 
"brcm,bcm6358-power-controller"
+- #power-domain-cells:  Should be <1>.
+- regmap:   The register map phandle
+- offset:   Offset in the register map for the power domain 
register (in bytes)
+- power-domain-indices: The bits in the register used for power domains.
+- power-domain-names:   Should be a list of strings of power domain names
+indexed by the power domain indices.
+
+Optional properties:
+- active-low:   Specify that the bits are active low.
+
+Example:
+
+misc_iddq_ctrl: power-controller {
+   compatible = "brcm,bcm63168-power-controller", 
"brcm,bcm6358-power-controller";
+   regmap = <&misc>;
+   offset = <0x4c>;
+
+   #power-domain-cells = <1>;
+   power-domain-indices =
+   <0>, <1>,  <2>,<3>, <4>,
+   <5>, <6>,  <7>,<8>, <9>,
+   <10>,<11>, <12>,   <13>,<17>,
+   <18>;
+   power-domain-names =
+   "sar",   "ipsec",  "mips", "dect",  "usbh",
+   "usbd",  "robosw", "pcm",  "periph","vdsl_phy",
+   "vdsl_mips", "fap","pcie", "wlan_pads", "gphy",
+   "gmac";
+   active-low;
+};
+
+periph_iddq: power-controller {
+   compatible = "brcm,bcm6368-power-controller", 
"brcm,bcm6358-power-controller";
+   regmap = <&periph_cntl>;
+   offset = <0x4>;
+
+   #power-domain-cells = <1>;
+   power-domain-indices = <19>;
+   power-domain-names = "usbh";
+};
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH linux-next] mtd: part: Add BCM962368 CFE partitioning support

2015-12-09 Thread Simon Arlott
Add partitioning support for BCM963268 boards with CFE bootloaders.
The following partitions are defined:
  "boot":   CFE and nvram data
  "rootfs": Currently selected rootfs
  "data":   Configuration data
  "rootfs1_update": Container for the whole flash area used
for the first rootfs to allow it to be
updated.
  "rootfs2_update": Container for the whole flash area used
for the second rootfs to allow it to be
updated.
  "rootfs_other":   The other (not currently selected) rootfs

Example:
[1.904302] nand: device found, Manufacturer ID: 0xc2, Chip ID: 0xf1
[1.911000] nand: Macronix NAND 128MiB 3,3V 8-bit
[1.915855] nand: 128 MiB, SLC, erase size: 128 KiB, page size: 2048, OOB 
size: 64
[1.923797] bcm6368_nand 1200.nand: detected 128MiB total, 128KiB 
blocks, 2KiB pages, 16B OOB, 8-bit, Hamming ECC
[1.936994] Bad block table found at page 65472, version 0x01
[1.944121] Bad block table found at page 65408, version 0x01
[1.951166] nand_read_bbt: bad block at 0x0748
[1.990043] bcm963268part: rootfs1: CFE boot tag found at 0x2 with 
version 6, board type 963168VX and sequence number 2
[2.003060] bcm963268part: rootfs2: CFE boot tag found at 0x400 with 
version 6, board type 963168VX and sequence number 1
[2.015159] bcm963268part: CFE bootline selected latest image rootfs1
[2.022080] 6 bcm963268part partitions found on MTD device brcmnand.0
[2.042659] Creating 6 MTD partitions on "brcmnand.0":
[2.048025] 0x-0x0002 : "boot"
[2.062134] 0x0004-0x0112 : "rootfs"
[2.077632] 0x07b0-0x07f0 : "data"
[2.091363] 0x0002-0x03ac : "rootfs1_update"
[2.106228] 0x0400-0x07ac : "rootfs2_update"
[2.121093] 0x0402-0x0506 : "rootfs_other"

The nvram contains the offset and size of the boot, rootfs1, rootfs2
and data partitions. The presence of CFE and nvram is verified by
reading from the boot partition which is assumed to be at offset 0
and the process aborts if the nvram read indicates that this is not
the case.

There is bcm_tag information at the start of each rootfs that is used
to determine which rootfs is newer and what its real offset/size is.

The CFE bootline or nvram partition number is used to select a rootfs.

Signed-off-by: Simon Arlott 
---
I'm aware that this is not compatible with the mtd partition/device tree
reorganisation patches and will rework the patch when this is committed.

Should I try to put the "struct bcm963268_nvram" in a common header file
for all 63xx SoCs? It's hard to know if there is only one purpose for
each byte in the nvram across all SoCs or whether it would be a complex
type involving unions for different SoCs.

The partitioning needs to match what exists already for this board so
that it's practical to swap between an flash image released by the
manufacturer/distributor of the hardware, and a custom image based on
the latest vanilla kernel.

 drivers/mtd/Kconfig |  21 +++
 drivers/mtd/Makefile|   1 +
 drivers/mtd/bcm963268part.c | 373 
 3 files changed, 395 insertions(+)
 create mode 100644 drivers/mtd/bcm963268part.c

diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 42cc953..63cb2db 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -148,6 +148,27 @@ config MTD_BCM63XX_PARTS
  This provides partions parsing for BCM63xx devices with CFE
  bootloaders.
 
+config MTD_BCM963268_PARTS
+   tristate "BCM963268 CFE partitioning support"
+   depends on BMIPS_GENERIC
+   select CRC32
+   help
+ This provides partitions parsing for BCM963268 boards with CFE
+ bootloaders. The following partitions are defined:
+   "boot":   CFE and nvram data
+   "rootfs": Currently selected rootfs
+   "data":   Configuration data
+   "rootfs1_update": Container for the whole flash area used
+ for the first rootfs to allow it to be
+ updated.
+   "rootfs2_update": Container for the whole flash area used
+ for the second rootfs to allow it to be
+ updated.
+   "rootfs_other":   The other (not currently selected) rootfs
+
+ A decision is made regarding which of the two rootfs is to be
+ used based on the nvram data.
+
 config MTD_BCM47XX_PARTS
tristate "BCM47XX partitioning support"
depends on BCM47XX || ARCH_BCM_5301X
diff --git a/drive

[PATCH linux-next (v2) 2/3] mtd: brcmnand: Request and enable the clock if present

2015-12-09 Thread Simon Arlott
Attempt to enable a clock named "nand" as some SoCs have a clock for the
controller that needs to be enabled.

Signed-off-by: Simon Arlott 
---
Resend, no changes.

 drivers/mtd/nand/brcmnand/brcmnand.c | 64 
 1 file changed, 50 insertions(+), 14 deletions(-)

diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c 
b/drivers/mtd/nand/brcmnand/brcmnand.c
index 190a99a..dca8162 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
@@ -11,6 +11,7 @@
  * GNU General Public License for more details.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -122,6 +123,9 @@ struct brcmnand_controller {
/* Some SoCs provide custom interrupt status register(s) */
struct brcmnand_soc *soc;
 
+   /* Some SoCs have a gateable clock for the controller */
+   struct clk  *clk;
+
int cmd_pending;
booldma_pending;
struct completion   done;
@@ -2127,10 +2131,24 @@ int brcmnand_probe(struct platform_device *pdev, struct 
brcmnand_soc *soc)
if (IS_ERR(ctrl->nand_base))
return PTR_ERR(ctrl->nand_base);
 
+   /* Enable clock before using NAND registers */
+   ctrl->clk = devm_clk_get(dev, "nand");
+   if (!IS_ERR(ctrl->clk)) {
+   ret = clk_prepare_enable(ctrl->clk);
+   if (ret)
+   return ret;
+   } else {
+   ret = PTR_ERR(ctrl->clk);
+   if (ret == -EPROBE_DEFER)
+   return ret;
+
+   ctrl->clk = NULL;
+   }
+
/* Initialize NAND revision */
ret = brcmnand_revision_init(ctrl);
if (ret)
-   return ret;
+   goto err;
 
/*
 * Most chips have this cache at a fixed offset within 'nand' block.
@@ -2139,8 +2157,10 @@ int brcmnand_probe(struct platform_device *pdev, struct 
brcmnand_soc *soc)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand-cache");
if (res) {
ctrl->nand_fc = devm_ioremap_resource(dev, res);
-   if (IS_ERR(ctrl->nand_fc))
-   return PTR_ERR(ctrl->nand_fc);
+   if (IS_ERR(ctrl->nand_fc)) {
+   ret = PTR_ERR(ctrl->nand_fc);
+   goto err;
+   }
} else {
ctrl->nand_fc = ctrl->nand_base +
ctrl->reg_offsets[BRCMNAND_FC_BASE];
@@ -2150,8 +2170,10 @@ int brcmnand_probe(struct platform_device *pdev, struct 
brcmnand_soc *soc)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "flash-dma");
if (res) {
ctrl->flash_dma_base = devm_ioremap_resource(dev, res);
-   if (IS_ERR(ctrl->flash_dma_base))
-   return PTR_ERR(ctrl->flash_dma_base);
+   if (IS_ERR(ctrl->flash_dma_base)) {
+   ret = PTR_ERR(ctrl->flash_dma_base);
+   goto err;
+   }
 
flash_dma_writel(ctrl, FLASH_DMA_MODE, 1); /* linked-list */
flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0);
@@ -2160,13 +2182,16 @@ int brcmnand_probe(struct platform_device *pdev, struct 
brcmnand_soc *soc)
ctrl->dma_desc = dmam_alloc_coherent(dev,
 sizeof(*ctrl->dma_desc),
 &ctrl->dma_pa, GFP_KERNEL);
-   if (!ctrl->dma_desc)
-   return -ENOMEM;
+   if (!ctrl->dma_desc) {
+   ret = -ENOMEM;
+   goto err;
+   }
 
ctrl->dma_irq = platform_get_irq(pdev, 1);
if ((int)ctrl->dma_irq < 0) {
dev_err(dev, "missing FLASH_DMA IRQ\n");
-   return -ENODEV;
+   ret = -ENODEV;
+   goto err;
}
 
ret = devm_request_irq(dev, ctrl->dma_irq,
@@ -2175,7 +2200,7 @@ int brcmnand_probe(struct platform_device *pdev, struct 
brcmnand_soc *soc)
if (ret < 0) {
dev_err(dev, "can't allocate IRQ %d: error %d\n",
ctrl->dma_irq, ret);
-   return ret;
+   goto err;
}
 
dev_info(dev, "enabling FLASH_DMA\n");
@@ -2199,7 +2224,8 @@ int brcmnand_probe(struct platform_device *pdev, struct 
brcmnand_soc *soc)
ctrl->irq = platform_get_irq(pdev, 0);
if ((int)ctrl->irq < 0) {
dev_err(dev, "no IRQ defined\n");
-   return -ENOD

[PATCH linux-next (v2) 3/3] mtd: brcmnand: Add support for the BCM6368

2015-12-09 Thread Simon Arlott
The BCM6368 has a NAND interrupt register with combined status and enable
registers.

As the BCM6328, BCM6362 and BCM6368 all use v2.1 controllers, the first
variant that will work with this driver is the BCM63268 using a v4.0
controller.

Set up the device by disabling and acking all interrupts, then handle
the CTRL_READY interrupt.

Signed-off-by: Simon Arlott 
---
Changed "nand-intr-base" reg name to "nand-int-base".

 drivers/mtd/nand/brcmnand/Makefile   |   1 +
 drivers/mtd/nand/brcmnand/bcm6368_nand.c | 145 +++
 2 files changed, 146 insertions(+)
 create mode 100644 drivers/mtd/nand/brcmnand/bcm6368_nand.c

diff --git a/drivers/mtd/nand/brcmnand/Makefile 
b/drivers/mtd/nand/brcmnand/Makefile
index 3b1fbfd..b28ffb59 100644
--- a/drivers/mtd/nand/brcmnand/Makefile
+++ b/drivers/mtd/nand/brcmnand/Makefile
@@ -2,5 +2,6 @@
 # more specific iproc_nand.o, for instance
 obj-$(CONFIG_MTD_NAND_BRCMNAND)+= iproc_nand.o
 obj-$(CONFIG_MTD_NAND_BRCMNAND)+= bcm63138_nand.o
+obj-$(CONFIG_MTD_NAND_BRCMNAND)+= bcm6368_nand.o
 obj-$(CONFIG_MTD_NAND_BRCMNAND)+= brcmstb_nand.o
 obj-$(CONFIG_MTD_NAND_BRCMNAND)+= brcmnand.o
diff --git a/drivers/mtd/nand/brcmnand/bcm6368_nand.c 
b/drivers/mtd/nand/brcmnand/bcm6368_nand.c
new file mode 100644
index 000..7f5359b
--- /dev/null
+++ b/drivers/mtd/nand/brcmnand/bcm6368_nand.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2015 Simon Arlott
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Derived from bcm63138_nand.c:
+ * Copyright © 2015 Broadcom Corporation
+ *
+ * Derived from 
bcm963xx_4.12L.06B_consumer/shared/opensource/include/bcm963xx/63268_map_part.h:
+ * Copyright 2000-2010 Broadcom Corporation
+ *
+ * Derived from 
bcm963xx_4.12L.06B_consumer/shared/opensource/flash/nandflash.c:
+ * Copyright 2000-2010 Broadcom Corporation
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "brcmnand.h"
+
+struct bcm6368_nand_soc {
+   struct brcmnand_soc soc;
+   void __iomem *base;
+};
+
+#define BCM6368_NAND_INT   0x00
+#define  BCM6368_NAND_STATUS_SHIFT 0
+#define  BCM6368_NAND_STATUS_MASK  (0xfff << BCM6368_NAND_STATUS_SHIFT)
+#define  BCM6368_NAND_ENABLE_SHIFT 16
+#define  BCM6368_NAND_ENABLE_MASK  (0x << BCM6368_NAND_ENABLE_SHIFT)
+#define BCM6368_NAND_BASE_ADDR00x04
+#define BCM6368_NAND_BASE_ADDR10x0c
+
+enum {
+   BCM6368_NP_READ = BIT(0),
+   BCM6368_BLOCK_ERASE = BIT(1),
+   BCM6368_COPY_BACK   = BIT(2),
+   BCM6368_PAGE_PGM= BIT(3),
+   BCM6368_CTRL_READY  = BIT(4),
+   BCM6368_DEV_RBPIN   = BIT(5),
+   BCM6368_ECC_ERR_UNC = BIT(6),
+   BCM6368_ECC_ERR_CORR= BIT(7),
+};
+
+static bool bcm6368_nand_intc_ack(struct brcmnand_soc *soc)
+{
+   struct bcm6368_nand_soc *priv =
+   container_of(soc, struct bcm6368_nand_soc, soc);
+   void __iomem *mmio = priv->base + BCM6368_NAND_INT;
+   u32 val = brcmnand_readl(mmio);
+
+   if (val & (BCM6368_CTRL_READY << BCM6368_NAND_STATUS_SHIFT)) {
+   /* Ack interrupt */
+   val &= ~BCM6368_NAND_STATUS_MASK;
+   val |= BCM6368_CTRL_READY << BCM6368_NAND_STATUS_SHIFT;
+   brcmnand_writel(val, mmio);
+   return true;
+   }
+
+   return false;
+}
+
+static void bcm6368_nand_intc_set(struct brcmnand_soc *soc, bool en)
+{
+   struct bcm6368_nand_soc *priv =
+   container_of(soc, struct bcm6368_nand_soc, soc);
+   void __iomem *mmio = priv->base + BCM6368_NAND_INT;
+   u32 val = brcmnand_readl(mmio);
+
+   /* Don't ack any interrupts */
+   val &= ~BCM6368_NAND_STATUS_MASK;
+
+   if (en)
+   val |= BCM6368_CTRL_READY << BCM6368_NAND_ENABLE_SHIFT;
+   else
+   val &= ~(BCM6368_CTRL_READY << BCM6368_NAND_ENABLE_SHIFT);
+
+   brcmnand_writel(val, mmio);
+}
+
+static int bcm6368_nand_probe(struct platform_device *pdev)
+{
+   struct device *dev = &pdev->dev;
+   struct bcm6368_nand_soc *priv;
+   struct brcmnand_soc *soc;
+   struct resource *res;
+
+   priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+   if (!priv)
+   return -ENOMEM;
+   soc = &priv->soc;
+
+   res = platform_get_resource_byname(pdev,
+   IORESOURCE_MEM, "

[PATCH linux-next (v2) 1/3] mtd: brcmnand: Add brcm,bcm6368-nand device tree binding

2015-12-09 Thread Simon Arlott
Add device tree binding for NAND on the BCM6368.

The BCM6368 has a NAND interrupt register with combined status and enable
registers. It also requires a clock, so add an optional clock to the
common brcmnand binding.

Signed-off-by: Simon Arlott 
---
Changed "nand-intr-base" reg name to "nand-int-base".

 .../devicetree/bindings/mtd/brcm,brcmnand.txt  | 32 ++
 1 file changed, 32 insertions(+)

diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt 
b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
index 4ff7128..ebfa6fc 100644
--- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
+++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
@@ -45,6 +45,8 @@ Required properties:
 - #size-cells  : <0>
 
 Optional properties:
+- clock : reference to the clock for the NAND controller
+- clock-names   : "nand" (required for the above clock)
 - brcm,nand-has-wp  : Some versions of this IP include a write-protect
   (WP) control bit. It is always available on >=
   v7.0. Use this property to describe the rare
@@ -72,6 +74,12 @@ we define additional 'compatible' properties and associated 
register resources w
and enable registers
  - reg-names: (required) "nand-int-base"
 
+   * "brcm,nand-bcm6368"
+ - compatible: should contain "brcm,nand-bcm", "brcm,nand-bcm6368"
+ - reg: (required) the 'NAND_INTR_BASE' register range, with combined 
status
+   and enable registers, and boot address registers
+ - reg-names: (required) "nand-int-base"
+
* "brcm,nand-iproc"
  - reg: (required) the "IDM" register range, for interrupt enable and APB
bus access endianness configuration, and the "EXT" register range,
@@ -148,3 +156,27 @@ nand@f0442800 {
};
};
 };
+
+nand@1200 {
+   compatible = "brcm,nand-bcm63168", "brcm,nand-bcm6368",
+   "brcm,brcmnand-v4.0", "brcm,brcmnand";
+   reg = <0x1200 0x180>,
+ <0x1600 0x200>,
+ <0x10b0 0x10>;
+   reg-names = "nand", "nand-cache", "nand-intr-base";
+   interrupt-parent = <&periph_intc>;
+   interrupts = <50>;
+   clocks = <&periph_clk 20>;
+   clock-names = "nand";
+
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   nand0: nandcs@0 {
+   compatible = "brcm,nandcs";
+   reg = <0>;
+   nand-on-flash-bbt;
+   nand-ecc-strength = <1>;
+   nand-ecc-step-size = <512>;
+   };
+};
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH linux-next 2/2] MIPS: bmips: Add bcm6345-l1 interrupt controller

2015-12-09 Thread Simon Arlott
Add the BCM6345 interrupt controller based on the SMP-capable BCM7038
and the BCM3380 but with packed interrupt registers.

Add the BCM6345 interrupt controller to a list with the existing BCM7038
so that interrupts on CPU1 are not ignored.

Update the maintainers file list for BMIPS to include this driver.

Signed-off-by: Simon Arlott 
---
Rebased against linux-next-20151209, no other changes.

 MAINTAINERS  |   1 +
 arch/mips/Kconfig|   1 +
 arch/mips/bmips/irq.c|  10 +-
 drivers/irqchip/Kconfig  |   5 +
 drivers/irqchip/Makefile |   1 +
 drivers/irqchip/irq-bcm6345-l1.c | 364 +++
 6 files changed, 380 insertions(+), 2 deletions(-)
 create mode 100644 drivers/irqchip/irq-bcm6345-l1.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 82f296a..9c49d4e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2387,6 +2387,7 @@ F:arch/mips/bmips/*
 F: arch/mips/include/asm/mach-bmips/*
 F: arch/mips/kernel/*bmips*
 F: arch/mips/boot/dts/brcm/bcm*.dts*
+F: drivers/irqchip/irq-bcm63*
 F: drivers/irqchip/irq-bcm7*
 F: drivers/irqchip/irq-brcmstb*
 
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index fbf3f66..9caf55a 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -151,6 +151,7 @@ config BMIPS_GENERIC
select CSRC_R4K
select SYNC_R4K
select COMMON_CLK
+   select BCM6345_L1_IRQ
select BCM7038_L1_IRQ
select BCM7120_L2_IRQ
select BRCMSTB_L2_IRQ
diff --git a/arch/mips/bmips/irq.c b/arch/mips/bmips/irq.c
index e7fc6f934..7efefcf 100644
--- a/arch/mips/bmips/irq.c
+++ b/arch/mips/bmips/irq.c
@@ -15,6 +15,12 @@
 #include 
 #include 
 
+static const struct of_device_id smp_intc_dt_match[] = {
+   { .compatible = "brcm,bcm7038-l1-intc" },
+   { .compatible = "brcm,bcm6345-l1-intc" },
+   {}
+};
+
 unsigned int get_c0_compare_int(void)
 {
return CP0_LEGACY_COMPARE_IRQ;
@@ -24,8 +30,8 @@ void __init arch_init_irq(void)
 {
struct device_node *dn;
 
-   /* Only the STB (bcm7038) controller supports SMP IRQ affinity */
-   dn = of_find_compatible_node(NULL, NULL, "brcm,bcm7038-l1-intc");
+   /* Only these controllers support SMP IRQ affinity */
+   dn = of_find_matching_node(NULL, smp_intc_dt_match);
if (dn)
of_node_put(dn);
else
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 4d7294e..d307bb3 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -65,6 +65,11 @@ config I8259
bool
select IRQ_DOMAIN
 
+config BCM6345_L1_IRQ
+   bool
+   select GENERIC_IRQ_CHIP
+   select IRQ_DOMAIN
+
 config BCM7038_L1_IRQ
bool
select GENERIC_IRQ_CHIP
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 177f78f..ded59cf 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -43,6 +43,7 @@ obj-$(CONFIG_XTENSA)  += irq-xtensa-pic.o
 obj-$(CONFIG_XTENSA_MX)+= irq-xtensa-mx.o
 obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o
 obj-$(CONFIG_SOC_VF610)+= irq-vf610-mscm-ir.o
+obj-$(CONFIG_BCM6345_L1_IRQ)   += irq-bcm6345-l1.o
 obj-$(CONFIG_BCM7038_L1_IRQ)   += irq-bcm7038-l1.o
 obj-$(CONFIG_BCM7120_L2_IRQ)   += irq-bcm7120-l2.o
 obj-$(CONFIG_BRCMSTB_L2_IRQ)   += irq-brcmstb-l2.o
diff --git a/drivers/irqchip/irq-bcm6345-l1.c b/drivers/irqchip/irq-bcm6345-l1.c
new file mode 100644
index 000..b844c89
--- /dev/null
+++ b/drivers/irqchip/irq-bcm6345-l1.c
@@ -0,0 +1,364 @@
+/*
+ * Broadcom BCM6345 style Level 1 interrupt controller driver
+ *
+ * Copyright (C) 2014 Broadcom Corporation
+ * Copyright 2015 Simon Arlott
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This is based on the BCM7038 (which supports SMP) but with a single
+ * enable register instead of separate mask/set/clear registers.
+ *
+ * The BCM3380 has a similar mask/status register layout, but each pair
+ * of words is at separate locations (and SMP is not supported).
+ *
+ * ENABLE/STATUS words are packed next to each other for each CPU:
+ *
+ * BCM6368:
+ *   0x1000_0020: CPU0_W0_ENABLE
+ *   0x1000_0024: CPU0_W1_ENABLE
+ *   0x1000_0028: CPU0_W0_STATUS   IRQs 31-63
+ *   0x1000_002c: CPU0_W1_STATUS   IRQs 0-31
+ *   0x1000_0030: CPU1_W0_ENABLE
+ *   0x1000_0034: CPU1_W1_ENABLE
+ *   0x1000_0038: CPU1_W0_STATUS   IRQs 31-63
+ *   0x1000_003c: CPU1_W1_STATUS   IRQs 0-31
+ *
+ * BCM63168:
+ *   0x1000_0020: CPU0_W0_ENABLE
+ *   0x1000_0024: CPU0_W1_ENABLE
+ *   0x1000_0028: CPU0_W2_ENABLE
+ *   0x1000_002c: CPU0_W3_ENABLE
+ *   0x1000_0030: CPU0_W0_STATUS   IRQs 96-127
+ *   0x1000_0

[PATCH linux-next 1/2] irqchip: Add brcm,bcm6345-l1-intc device tree binding

2015-12-09 Thread Simon Arlott
Add device tree binding for the BCM6345 interrupt controller.

This controller is similar to the SMP-capable BCM7038 and
the BCM3380 but with packed interrupt registers.

Signed-off-by: Simon Arlott 
---
Corrected example device name to be "interrupt-controller".

 .../interrupt-controller/brcm,bcm6345-l1-intc.txt  | 57 ++
 1 file changed, 57 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-l1-intc.txt

diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-l1-intc.txt
 
b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-l1-intc.txt
new file mode 100644
index 000..4040905
--- /dev/null
+++ 
b/Documentation/devicetree/bindings/interrupt-controller/brcm,bcm6345-l1-intc.txt
@@ -0,0 +1,57 @@
+Broadcom BCM6345-style Level 1 interrupt controller
+
+This block is a first level interrupt controller that is typically connected
+directly to one of the HW INT lines on each CPU.
+
+Key elements of the hardware design include:
+
+- 32, 64 or 128 incoming level IRQ lines
+
+- Most onchip peripherals are wired directly to an L1 input
+
+- A separate instance of the register set for each CPU, allowing individual
+  peripheral IRQs to be routed to any CPU
+
+- Contains one or more enable/status word pairs per CPU
+
+- No atomic set/clear operations
+
+- No polarity/level/edge settings
+
+- No FIFO or priority encoder logic; software is expected to read all
+  2-4 status words to determine which IRQs are pending
+
+Required properties:
+
+- compatible: should be "brcm,bcm-l1-intc", "brcm,bcm6345-l1-intc"
+- reg: specifies the base physical address and size of the registers;
+  the number of supported IRQs is inferred from the size argument
+- interrupt-controller: identifies the node as an interrupt controller
+- #interrupt-cells: specifies the number of cells needed to encode an interrupt
+  source, should be 1.
+- interrupt-parent: specifies the phandle to the parent interrupt controller(s)
+  this one is cascaded from
+- interrupts: specifies the interrupt line(s) in the interrupt-parent 
controller
+  node; valid values depend on the type of parent interrupt controller
+
+If multiple reg ranges and interrupt-parent entries are present on an SMP
+system, the driver will allow IRQ SMP affinity to be set up through the
+/proc/irq/ interface.  In the simplest possible configuration, only one
+reg range and one interrupt-parent is needed.
+
+The driver operates in native CPU endian by default, there is no support for
+specifying an alternative endianness.
+
+Example:
+
+periph_intc: interrupt-controller@1000 {
+compatible = "brcm,bcm63168-l1-intc", "brcm,bcm6345-l1-intc";
+reg = <0x1020 0x20>,
+  <0x1040 0x20>;
+
+interrupt-controller;
+#interrupt-cells = <1>;
+
+interrupt-parent = <&cpu_intc>;
+interrupts = <2>, <3>;
+};
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] clk: Add brcm,bcm63xx-gate-clk device tree binding

2015-12-08 Thread Simon Arlott
On Fri, December 4, 2015 21:04, Simon Arlott wrote:
> On Fri, December 4, 2015 14:30, Rob Herring wrote:
>> On Mon, Nov 30, 2015 at 08:52:55PM +0000, Simon Arlott wrote:
>>> +periph_clk: periph_clk {
>>> +   compatible = "brcm,bcm63168-gate-clk", "brcm,bcm63xx-gate-clk";
>>> +   regmap = <&periph_cntl>;
>>
>> What else is in periph_cntrl? Could this all just be part of that node?
>
>  uint32RevID; /* (00) word 0 */
>  uint32blkEnables;/* (04) word 1 */ <-- gated clocks
>  uint32pll_control;   /* (08) word 2 */ <-- system reset 
> controller bit
>  uint32deviceTimeoutEn;   /* (0c) word 3 */ <-- unknown
>  uint32softResetB;/* (10) word 4 */ <-- device reset 
> controller bits
> uint32diagControl;/* (14) word 5 */ <-- unknown
> uint32ExtIrqCfg;  /* (18) word 6*/ <-- external interrupt 
> controller
> uint32unused1;/* (1c) word 7 */ <-- (external 
> interrupt controller?)
>  IrqControl_t IrqControl[3];/* (20) (40) (60) */ <-- normal 
> interrupt controller

On the BCM6368 [1], blkEnables also conatains a power domain bit:
 uint32blkEnables;/* (04) word 1 */
#define USBH_IDDQ_EN (1 << 19)
#define IPSEC_CLK_EN (1 << 18)
#define NAND_CLK_EN  (1 << 17)
#define DISABLE_GLESS(1 << 16)
#define USBH_CLK_EN  (1 << 15)
#define PCM_CLK_EN   (1 << 14)
#define UTOPIA_CLK_EN(1 << 13)
#define ROBOSW_CLK_EN(1 << 12)
#define SAR_CLK_EN   (1 << 11)
#define USBD_CLK_EN  (1 << 10)
#define SPI_CLK_EN   (1 << 9)
#define SWPKT_SAR_CLK_EN (1 << 8)
#define SWPKT_USB_CLK_EN (1 << 7)
#define PHYMIPS_CLK_EN   (1 << 6)
#define VDSL_CLK_EN  (1 << 5)
#define VDSL_BONDING_EN  (1 << 4)
#define VDSL_AFE_EN  (1 << 3)
#define VDSL_QPROC_EN(1 << 2)

In order to be able to map these to devices for the BCM63xx SoCs I'm going
to define the power controller binding with "power-domain-indices" and
"power-domain-names" to mirror the clock binding. The separate clk and
generic_pm_domain devices will then handle set/clear of the relevant bits
using the regmap.


[1]
https://code.google.com/p/gfiber-gflt100/source/browse/shared/opensource/include/bcm963xx/6368_map_part.h?r=b292e8c271addbda62104bece90e3c8018714194

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/3] mtd: brcmnand: Add brcm,bcm6368-nand device tree binding

2015-12-04 Thread Simon Arlott
On Fri, December 4, 2015 16:04, Jonas Gorski wrote:
> On Thu, Dec 3, 2015 at 12:41 AM, Simon Arlott  wrote:
>> +   * "brcm,nand-bcm6368"
>> + - compatible: should contain "brcm,nand-bcm", "brcm,nand-bcm6368"
>> + - reg: (required) the 'NAND_INTR_BASE' register range, with combined 
>> status
>> +   and enable registers, and boot address registers
>> + - reg-names: (required) "nand-intr-base"
>
> Can't we use the same name as bcm63138, i.e. nand-int-base?

Brian,

Before I change this, is there anything else in the patch series that needs to
be changed?

(I'll keep the comment referring to "NAND_INTR_BASE" the same because that's 
the name
in the original #define for this hardware.)

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH (v2) 1/2] reset: Add brcm,bcm6345-reset device tree binding

2015-12-04 Thread Simon Arlott
On Thu, December 3, 2015 08:39, Philipp Zabel wrote:
> Am Mittwoch, den 02.12.2015, 21:03 + schrieb Simon Arlott:
>> +periph_soft_rst: reset-controller {
>> +compatible = "brcm,bcm63168-reset", "brcm,bcm6345-reset";
>> +regmap = <&periph_cntl>;
>> +offset = <0x10>;
>> +
>> +#reset-cells = <1>;
>> +};
>
> I would have written it something like this:
>
> periph_cntl: ... {
>   compatible = "syscon", "simple-mfd";
>   #address-cells = <1>;
>   #size-cells = <1>;
>
>   periph_soft_rst: reset-controller {
>   compatible = "brcm,bcm6345-reset";
>   reg = <0x10 0x4>;
>   #reset-cells = <1>;
>   };
> };
>
> for a device that is only controlled through a syscon.

Rob, do you want me to change this or is my version ok?

> The driver itself looks good to me.
>
> best regards
> Philipp
>
>

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] clk: Add brcm,bcm63xx-gate-clk device tree binding

2015-12-04 Thread Simon Arlott
On Fri, December 4, 2015 14:30, Rob Herring wrote:
> On Mon, Nov 30, 2015 at 08:52:55PM +0000, Simon Arlott wrote:
>> +periph_clk: periph_clk {
>> +compatible = "brcm,bcm63168-gate-clk", "brcm,bcm63xx-gate-clk";
>> +regmap = <&periph_cntl>;
>
> What else is in periph_cntrl? Could this all just be part of that node?

 uint32RevID; /* (00) word 0 */
 uint32blkEnables;/* (04) word 1 */ <-- gated clocks
 uint32pll_control;   /* (08) word 2 */ <-- system reset 
controller bit
 uint32deviceTimeoutEn;   /* (0c) word 3 */ <-- unknown
 uint32softResetB;/* (10) word 4 */ <-- device reset 
controller bits
uint32diagControl;/* (14) word 5 */ <-- unknown
uint32ExtIrqCfg;  /* (18) word 6*/ <-- external interrupt 
controller
uint32unused1;/* (1c) word 7 */ <-- (external interrupt 
controller?)
 IrqControl_t IrqControl[3];/* (20) (40) (60) */ <-- normal 
interrupt controller

So it has these clocks, two types of reset controller, and the interrupt
controllers, but I've left the interrupt controllers registers out of the
syscon device.

For the registers in the "timer" peripheral at the end of the timer/watchdog
registers:
uint32EnSwPLL; <-- unknown
uint32ClkRstCtl;
#define POR_RESET_STATUS(1 << 31) <-- unknown
#define HW_RESET_STATUS (1 << 30) <-- unknown
#define SW_RESET_STATUS (1 << 29) <-- unknown
#define USB_REF_CLKEN   (1 << 18) <-- gated clock
#define UTO_EXTIN_CLKEN (1 << 17) <-- gated clock
#define UTO_CLK50_SEL   (1 << 16) <-- looks like a clock frequency 
selection bit
#define FAP2_PLL_CLKEN  (1 << 15) <-- gated clock
#define FAP2_PLL_FREQ_SHIFT 12<-- bits for controlling the 
frequency
#define FAP1_PLL_CLKEN  (1 << 11) <-- gated clock
#define FAP1_PLL_FREQ_SHIFT 8 <-- bits for controlling the 
frequency
#define WAKEON_DSL  (1 << 7)  <-- wake on network bit
#define WAKEON_EPHY (1 << 6)  <-- wake on network bit
#define DSL_ENERGY_DETECT_ENABLE(1 << 4)  <-- energy saving control for 
network
#define GPHY_1_ENERGY_DETECT_ENABLE (1 << 3)  <-- energy saving control for 
network
#define EPHY_3_ENERGY_DETECT_ENABLE (1 << 2)  <-- energy saving control for 
network
#define EPHY_2_ENERGY_DETECT_ENABLE (1 << 1)  <-- energy saving control for 
network
#define EPHY_1_ENERGY_DETECT_ENABLE (1 << 0)  <-- energy saving control for 
network

I need the usb_ref clock for USB, and I want to be able to disable
uto_extin, fap1 and fap2 as they're unused by anything in the device tree.

The full list of registers is here:
https://github.com/lp0/bcm963xx_4.12L.06B_consumer/blob/master/shared/opensource/include/bcm963xx/63268_map_part.h

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] regulator: Add brcm,bcm63xx-regulator device tree binding

2015-12-04 Thread Simon Arlott
On Fri, December 4, 2015 11:00, Mark Brown wrote:
> On Thu, Dec 03, 2015 at 11:51:16PM +0000, Simon Arlott wrote:
>> On 03/12/15 23:45, Mark Brown wrote:
>
>> > Are you *sure* these are regulators and not power domains?  These names
>> > look a lot like they could be power domains.
>
>> No, I'm not sure. Some of them are may actually be regulators (the "PHY"
>> ones) while others are almost definitely power domains (like the "FAP"
>> Forwarding Assist Processor).
>
> OK, so the power domains should be being represented and managed as such
> rather than using regulators - it's a better fit (doing things like
> support atomic context) and it also sidesteps this.  For the things that
> you say are clearly regulators should we have more information about
> those?

I'd prefer to handle them all as power domains since it fits better. Even
if some of them are regulators there's no extra control or status interface
and they're used like power domains to disable unused functionality.

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] regulator: Add brcm,bcm63xx-regulator device tree binding

2015-12-03 Thread Simon Arlott
On 03/12/15 23:45, Mark Brown wrote:
> On Thu, Dec 03, 2015 at 11:38:28PM +0000, Simon Arlott wrote:
> 
>> #define MISC_IDDQ_CTRL_GMAC (1<<18)
>> #define MISC_IDDQ_CTRL_WLAN_PADS(1<<13)
>> #define MISC_IDDQ_CTRL_PCIE (1<<12)
>> #define MISC_IDDQ_CTRL_FAP  (1<<11)
>> #define MISC_IDDQ_CTRL_VDSL_MIPS(1<<10)
>> #define MISC_IDDQ_CTRL_VDSL_PHY (1<<9)
>> #define MISC_IDDQ_CTRL_PERIPH   (1<<8)
>> #define MISC_IDDQ_CTRL_PCM  (1<<7)
>> #define MISC_IDDQ_CTRL_ROBOSW   (1<<6)
>> #define MISC_IDDQ_CTRL_USBD (1<<5)
>> #define MISC_IDDQ_CTRL_USBH (1<<4)
>> #define MISC_IDDQ_CTRL_DECT (1<<3)
>> #define MISC_IDDQ_CTRL_MIPS (1<<2)
>> #define MISC_IDDQ_CTRL_IPSEC(1<<1)
>> #define MISC_IDDQ_CTRL_SAR  (1<<0)
> 
> Are you *sure* these are regulators and not power domains?  These names
> look a lot like they could be power domains.

No, I'm not sure. Some of them are may actually be regulators (the "PHY"
ones) while others are almost definitely power domains (like the "FAP"
Forwarding Assist Processor).

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] regulator: Add brcm,bcm63xx-regulator device tree binding

2015-12-03 Thread Simon Arlott
On 03/12/15 15:05, Mark Brown wrote:
> On Thu, Dec 03, 2015 at 08:14:33AM +0000, Simon Arlott wrote:
>> On 03/12/15 00:06, Mark Brown wrote:
> 
>> > this it should know at least something about how to control the device
>> > from the compatible string.  If you're making a generic driver it should
>> > not make reference to specific devices.
> 
>> Will you accept a generic driver for a simple enable regulator device on
>> a regmap? What should its compatible string be?
> 
> Perhaps.  I really don't like putting the entire driver into DT, it's
> not a pattern I want to encourage.

I don't like putting the list of which bit is which regulator name into
a driver because it means that new hardware that adds a regulator or
moves them around requires a change to the driver.

Documentation/devicetree/usage-model.txt:
  2.1 High Level View
  ---
  [...] Using
  it allows board and device support to become data driven; to make
  setup decisions based on data passed into the kernel instead of on
  per-machine hard coded selections.

I agree that an entire driver shouldn't be put in the DT (especially
given that you then need the DT to debug any issue), but this isn't much
of a driver when it involves flipping a single bit.

The key thing would be to avoid it growing into something too complex
(e.g. set register X to 42 to enable and set register Y to 90 to
disable, would not belong in DT).

Should I be looking at trying to use generic_pm_domain instead of a
regulator? Those don't appear to require a name so a phandle with an
argument for the bit would work.

>> > There could be one if it would help, but we do normally manage to do
>> > this without - look at how other regulator drivers work.
> 
>> Several of them have a fixed list of supported regulator names in the
> 
> Yes, that's the way this is handled.

I see two variants of the hardware bits (three if you consider that the
GMAC isn't on every SoC):

#define MISC_IDDQ_CTRL_GMAC (1<<18)
#define MISC_IDDQ_CTRL_WLAN_PADS(1<<13)
#define MISC_IDDQ_CTRL_PCIE (1<<12)
#define MISC_IDDQ_CTRL_FAP  (1<<11)
#define MISC_IDDQ_CTRL_VDSL_MIPS(1<<10)
#define MISC_IDDQ_CTRL_VDSL_PHY (1<<9)
#define MISC_IDDQ_CTRL_PERIPH   (1<<8)
#define MISC_IDDQ_CTRL_PCM  (1<<7)
#define MISC_IDDQ_CTRL_ROBOSW   (1<<6)
#define MISC_IDDQ_CTRL_USBD (1<<5)
#define MISC_IDDQ_CTRL_USBH (1<<4)
#define MISC_IDDQ_CTRL_DECT (1<<3)
#define MISC_IDDQ_CTRL_MIPS (1<<2)
#define MISC_IDDQ_CTRL_IPSEC(1<<1)
#define MISC_IDDQ_CTRL_SAR  (1<<0)

#define MISC_IDDQ_CTRL_EPHY (1<<9)
#define MISC_IDDQ_CTRL_ROBOSW   (1<<8)
#define MISC_IDDQ_CTRL_PCIE (1<<7)
#define MISC_IDDQ_CTRL_USBH (1<<6)
#define MISC_IDDQ_CTRL_USBD (1<<5)
#define MISC_IDDQ_CTRL_PCM  (1<<4)
#define MISC_IDDQ_CTRL_SAR  (1<<3)
#define MISC_IDDQ_CTRL_ADSL2_AFE(1<<2)
#define MISC_IDDQ_CTRL_ADSL2_PHY(1<<1)
#define MISC_IDDQ_CTRL_ADSL2_MIPS   (1<<0)

I could put these lists of bits in a driver (associated with the names)
but I'd strongly prefer to put the list of bits in the DT.

If they are in the driver, then there is nothing to stop someone from
deciding to force it to fit a different new piece of hardware by
deliberately using the wrong names in the DT just because they match
the bits they want to use, and they think they can't wait for a new 
list of bits to be added to the kernel.

e.g. someone adds an LTE chip and reuses the obsolete DECT regulator:

misc_iddq_ctrl@42 {
  compatible = "...-regulator";
  reg = <0x42>;

  regulators {
lte_power: dect {
  regulator-name = "LTE";
};
  };
};

Associating the bits with the names in the DT avoids this problem at
the expense of having a very generic driver.

A lot of the existing regulator drivers have mostly numbered regulator
pins which could have been connected to anything on a hardware variant.

>> driver. The regulator names for this device are meaningless to the
>> driver because all of the regulators look the same. They don't have a
>> known or controllable voltage and can only be turned on or off.
> 
> Nonsense.  The names are useful to identify which supply is being
> referred to.  Having voltage control is irrelevant to identifying
> regulators.

Ok, but from the driver's point of view there's nothing different about
any of the regulators on this hardware. I could have numbered them
"BIT0" to "BIT31" in the driver and used a meaningful alias in DT.

>> Any table mapping regulator names to bits in the register would be

[PATCH linux-next 3/3] mtd: brcmnand: Add support for the BCM6368

2015-12-03 Thread Simon Arlott
The BCM6368 has a NAND interrupt register with combined status and enable
registers.

As the BCM6328, BCM6362 and BCM6368 all use v2.1 controllers, the first
variant that will work with this driver is the BCM63268 using a v4.0
controller.

Set up the device by disabling and acking all interrupts, then handle
the CTRL_READY interrupt.

Signed-off-by: Simon Arlott 
---
 drivers/mtd/nand/brcmnand/Makefile   |   1 +
 drivers/mtd/nand/brcmnand/bcm6368_nand.c | 145 +++
 2 files changed, 146 insertions(+)
 create mode 100644 drivers/mtd/nand/brcmnand/bcm6368_nand.c

diff --git a/drivers/mtd/nand/brcmnand/Makefile 
b/drivers/mtd/nand/brcmnand/Makefile
index 3b1fbfd..b28ffb59 100644
--- a/drivers/mtd/nand/brcmnand/Makefile
+++ b/drivers/mtd/nand/brcmnand/Makefile
@@ -2,5 +2,6 @@
 # more specific iproc_nand.o, for instance
 obj-$(CONFIG_MTD_NAND_BRCMNAND)+= iproc_nand.o
 obj-$(CONFIG_MTD_NAND_BRCMNAND)+= bcm63138_nand.o
+obj-$(CONFIG_MTD_NAND_BRCMNAND)+= bcm6368_nand.o
 obj-$(CONFIG_MTD_NAND_BRCMNAND)+= brcmstb_nand.o
 obj-$(CONFIG_MTD_NAND_BRCMNAND)+= brcmnand.o
diff --git a/drivers/mtd/nand/brcmnand/bcm6368_nand.c 
b/drivers/mtd/nand/brcmnand/bcm6368_nand.c
new file mode 100644
index 000..c347ea5
--- /dev/null
+++ b/drivers/mtd/nand/brcmnand/bcm6368_nand.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2015 Simon Arlott
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Derived from bcm63138_nand.c:
+ * Copyright © 2015 Broadcom Corporation
+ *
+ * Derived from 
bcm963xx_4.12L.06B_consumer/shared/opensource/include/bcm963xx/63268_map_part.h:
+ * Copyright 2000-2010 Broadcom Corporation
+ *
+ * Derived from 
bcm963xx_4.12L.06B_consumer/shared/opensource/flash/nandflash.c:
+ * Copyright 2000-2010 Broadcom Corporation
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "brcmnand.h"
+
+struct bcm6368_nand_soc {
+   struct brcmnand_soc soc;
+   void __iomem *base;
+};
+
+#define BCM6368_NAND_INT   0x00
+#define  BCM6368_NAND_STATUS_SHIFT 0
+#define  BCM6368_NAND_STATUS_MASK  (0xfff << BCM6368_NAND_STATUS_SHIFT)
+#define  BCM6368_NAND_ENABLE_SHIFT 16
+#define  BCM6368_NAND_ENABLE_MASK  (0x << BCM6368_NAND_ENABLE_SHIFT)
+#define BCM6368_NAND_BASE_ADDR00x04
+#define BCM6368_NAND_BASE_ADDR10x0c
+
+enum {
+   BCM6368_NP_READ = BIT(0),
+   BCM6368_BLOCK_ERASE = BIT(1),
+   BCM6368_COPY_BACK   = BIT(2),
+   BCM6368_PAGE_PGM= BIT(3),
+   BCM6368_CTRL_READY  = BIT(4),
+   BCM6368_DEV_RBPIN   = BIT(5),
+   BCM6368_ECC_ERR_UNC = BIT(6),
+   BCM6368_ECC_ERR_CORR= BIT(7),
+};
+
+static bool bcm6368_nand_intc_ack(struct brcmnand_soc *soc)
+{
+   struct bcm6368_nand_soc *priv =
+   container_of(soc, struct bcm6368_nand_soc, soc);
+   void __iomem *mmio = priv->base + BCM6368_NAND_INT;
+   u32 val = brcmnand_readl(mmio);
+
+   if (val & (BCM6368_CTRL_READY << BCM6368_NAND_STATUS_SHIFT)) {
+   /* Ack interrupt */
+   val &= ~BCM6368_NAND_STATUS_MASK;
+   val |= BCM6368_CTRL_READY << BCM6368_NAND_STATUS_SHIFT;
+   brcmnand_writel(val, mmio);
+   return true;
+   }
+
+   return false;
+}
+
+static void bcm6368_nand_intc_set(struct brcmnand_soc *soc, bool en)
+{
+   struct bcm6368_nand_soc *priv =
+   container_of(soc, struct bcm6368_nand_soc, soc);
+   void __iomem *mmio = priv->base + BCM6368_NAND_INT;
+   u32 val = brcmnand_readl(mmio);
+
+   /* Don't ack any interrupts */
+   val &= ~BCM6368_NAND_STATUS_MASK;
+
+   if (en)
+   val |= BCM6368_CTRL_READY << BCM6368_NAND_ENABLE_SHIFT;
+   else
+   val &= ~(BCM6368_CTRL_READY << BCM6368_NAND_ENABLE_SHIFT);
+
+   brcmnand_writel(val, mmio);
+}
+
+static int bcm6368_nand_probe(struct platform_device *pdev)
+{
+   struct device *dev = &pdev->dev;
+   struct bcm6368_nand_soc *priv;
+   struct brcmnand_soc *soc;
+   struct resource *res;
+
+   priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+   if (!priv)
+   return -ENOMEM;
+   soc = &priv->soc;
+
+   res = platform_get_resource_byname(pdev,
+   IORESOURCE_MEM, "nand-intr-base");
+   if (!res)
+   retu

[PATCH linux-next 2/3] mtd: brcmnand: Request and enable the clock if present

2015-12-03 Thread Simon Arlott
Attempt to enable a clock named "nand" as some SoCs have a clock for the
controller that needs to be enabled.

Signed-off-by: Simon Arlott 
---
Removed ctrl->clk not NULL check.

 drivers/mtd/nand/brcmnand/brcmnand.c | 64 
 1 file changed, 50 insertions(+), 14 deletions(-)

diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c 
b/drivers/mtd/nand/brcmnand/brcmnand.c
index 35d78f7..cf0374e 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
@@ -11,6 +11,7 @@
  * GNU General Public License for more details.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -122,6 +123,9 @@ struct brcmnand_controller {
/* Some SoCs provide custom interrupt status register(s) */
struct brcmnand_soc *soc;
 
+   /* Some SoCs have a gateable clock for the controller */
+   struct clk  *clk;
+
int cmd_pending;
booldma_pending;
struct completion   done;
@@ -2127,10 +2131,24 @@ int brcmnand_probe(struct platform_device *pdev, struct 
brcmnand_soc *soc)
if (IS_ERR(ctrl->nand_base))
return PTR_ERR(ctrl->nand_base);
 
+   /* Enable clock before using NAND registers */
+   ctrl->clk = devm_clk_get(dev, "nand");
+   if (!IS_ERR(ctrl->clk)) {
+   ret = clk_prepare_enable(ctrl->clk);
+   if (ret)
+   return ret;
+   } else {
+   ret = PTR_ERR(ctrl->clk);
+   if (ret == -EPROBE_DEFER)
+   return ret;
+
+   ctrl->clk = NULL;
+   }
+
/* Initialize NAND revision */
ret = brcmnand_revision_init(ctrl);
if (ret)
-   return ret;
+   goto err;
 
/*
 * Most chips have this cache at a fixed offset within 'nand' block.
@@ -2139,8 +2157,10 @@ int brcmnand_probe(struct platform_device *pdev, struct 
brcmnand_soc *soc)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand-cache");
if (res) {
ctrl->nand_fc = devm_ioremap_resource(dev, res);
-   if (IS_ERR(ctrl->nand_fc))
-   return PTR_ERR(ctrl->nand_fc);
+   if (IS_ERR(ctrl->nand_fc)) {
+   ret = PTR_ERR(ctrl->nand_fc);
+   goto err;
+   }
} else {
ctrl->nand_fc = ctrl->nand_base +
ctrl->reg_offsets[BRCMNAND_FC_BASE];
@@ -2150,8 +2170,10 @@ int brcmnand_probe(struct platform_device *pdev, struct 
brcmnand_soc *soc)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "flash-dma");
if (res) {
ctrl->flash_dma_base = devm_ioremap_resource(dev, res);
-   if (IS_ERR(ctrl->flash_dma_base))
-   return PTR_ERR(ctrl->flash_dma_base);
+   if (IS_ERR(ctrl->flash_dma_base)) {
+   ret = PTR_ERR(ctrl->flash_dma_base);
+   goto err;
+   }
 
flash_dma_writel(ctrl, FLASH_DMA_MODE, 1); /* linked-list */
flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0);
@@ -2160,13 +2182,16 @@ int brcmnand_probe(struct platform_device *pdev, struct 
brcmnand_soc *soc)
ctrl->dma_desc = dmam_alloc_coherent(dev,
 sizeof(*ctrl->dma_desc),
 &ctrl->dma_pa, GFP_KERNEL);
-   if (!ctrl->dma_desc)
-   return -ENOMEM;
+   if (!ctrl->dma_desc) {
+   ret = -ENOMEM;
+   goto err;
+   }
 
ctrl->dma_irq = platform_get_irq(pdev, 1);
if ((int)ctrl->dma_irq < 0) {
dev_err(dev, "missing FLASH_DMA IRQ\n");
-   return -ENODEV;
+   ret = -ENODEV;
+   goto err;
}
 
ret = devm_request_irq(dev, ctrl->dma_irq,
@@ -2175,7 +2200,7 @@ int brcmnand_probe(struct platform_device *pdev, struct 
brcmnand_soc *soc)
if (ret < 0) {
dev_err(dev, "can't allocate IRQ %d: error %d\n",
ctrl->dma_irq, ret);
-   return ret;
+   goto err;
}
 
dev_info(dev, "enabling FLASH_DMA\n");
@@ -2199,7 +2224,8 @@ int brcmnand_probe(struct platform_device *pdev, struct 
brcmnand_soc *soc)
ctrl->irq = platform_get_irq(pdev, 0);
if ((int)ctrl->irq < 0) {
dev_err(dev, "no IRQ defined\n");
-   return -E

[PATCH linux-next 1/3] mtd: brcmnand: Add brcm,bcm6368-nand device tree binding

2015-12-03 Thread Simon Arlott
Add device tree binding for NAND on the BCM6368.

The BCM6368 has a NAND interrupt register with combined status and enable
registers. It also requires a clock, so add an optional clock to the
common brcmnand binding.

Signed-off-by: Simon Arlott 
---
 .../devicetree/bindings/mtd/brcm,brcmnand.txt  | 32 ++
 1 file changed, 32 insertions(+)

diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt 
b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
index 4ff7128..16d7835 100644
--- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
+++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
@@ -45,6 +45,8 @@ Required properties:
 - #size-cells  : <0>
 
 Optional properties:
+- clock : reference to the clock for the NAND controller
+- clock-names   : "nand" (required for the above clock)
 - brcm,nand-has-wp  : Some versions of this IP include a write-protect
   (WP) control bit. It is always available on >=
   v7.0. Use this property to describe the rare
@@ -72,6 +74,12 @@ we define additional 'compatible' properties and associated 
register resources w
and enable registers
  - reg-names: (required) "nand-int-base"
 
+   * "brcm,nand-bcm6368"
+ - compatible: should contain "brcm,nand-bcm", "brcm,nand-bcm6368"
+ - reg: (required) the 'NAND_INTR_BASE' register range, with combined 
status
+   and enable registers, and boot address registers
+ - reg-names: (required) "nand-intr-base"
+
* "brcm,nand-iproc"
  - reg: (required) the "IDM" register range, for interrupt enable and APB
bus access endianness configuration, and the "EXT" register range,
@@ -148,3 +156,27 @@ nand@f0442800 {
};
};
 };
+
+nand@1200 {
+   compatible = "brcm,nand-bcm63168", "brcm,nand-bcm6368",
+   "brcm,brcmnand-v4.0", "brcm,brcmnand";
+   reg = <0x1200 0x180>,
+ <0x1600 0x200>,
+ <0x10b0 0x10>;
+   reg-names = "nand", "nand-cache", "nand-intr-base";
+   interrupt-parent = <&periph_intc>;
+   interrupts = <50>;
+   clocks = <&periph_clk 20>;
+   clock-names = "nand";
+
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   nand0: nandcs@0 {
+   compatible = "brcm,nandcs";
+   reg = <0>;
+   nand-on-flash-bbt;
+   nand-ecc-strength = <1>;
+   nand-ecc-step-size = <512>;
+   };
+};
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH linux-next 2/2] clk: bcm6345: Add BCM6345 gated clock support

2015-12-03 Thread Simon Arlott
The BCM6345 contains clocks gated with a register. Clocks are indexed
by bits in the register and are active high. Clock gate bits are
interleaved with other status bits and configurable clocks in the same
register.

Enabled by default for BMIPS_GENERIC.

Signed-off-by: Simon Arlott 
---
Renamed to BCM6345.

 MAINTAINERS   |   1 +
 drivers/clk/bcm/Kconfig   |   9 ++
 drivers/clk/bcm/Makefile  |   1 +
 drivers/clk/bcm/clk-bcm6345.c | 191 ++
 4 files changed, 202 insertions(+)
 create mode 100644 drivers/clk/bcm/clk-bcm6345.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 577e5ea..9a61f48 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2381,6 +2381,7 @@ F:arch/mips/bmips/*
 F: arch/mips/include/asm/mach-bmips/*
 F: arch/mips/kernel/*bmips*
 F: arch/mips/boot/dts/brcm/bcm*.dts*
+F: drivers/clk/bcm/clk-bcm6345*
 F: drivers/irqchip/irq-bcm63*
 F: drivers/irqchip/irq-bcm7*
 F: drivers/irqchip/irq-brcmstb*
diff --git a/drivers/clk/bcm/Kconfig b/drivers/clk/bcm/Kconfig
index f287845..043353a 100644
--- a/drivers/clk/bcm/Kconfig
+++ b/drivers/clk/bcm/Kconfig
@@ -8,6 +8,15 @@ config CLK_BCM_63XX
  Enable common clock framework support for Broadcom BCM63xx DSL SoCs
  based on the ARM architecture
 
+config CLK_BCM_6345
+   bool "Broadcom BCM6345 clock support"
+   depends on BMIPS_GENERIC || COMPILE_TEST
+   depends on COMMON_CLK
+   default BMIPS_GENERIC
+   help
+ Enable common clock framework support for Broadcom BCM6345 DSL SoCs
+ based on the MIPS architecture
+
 config CLK_BCM_KONA
bool "Broadcom Kona CCU clock support"
depends on ARCH_BCM_MOBILE || COMPILE_TEST
diff --git a/drivers/clk/bcm/Makefile b/drivers/clk/bcm/Makefile
index 247c267..e2bac43 100644
--- a/drivers/clk/bcm/Makefile
+++ b/drivers/clk/bcm/Makefile
@@ -1,4 +1,5 @@
 obj-$(CONFIG_CLK_BCM_63XX) += clk-bcm63xx.o
+obj-$(CONFIG_CLK_BCM_6345) += clk-bcm6345.o
 obj-$(CONFIG_CLK_BCM_KONA) += clk-kona.o
 obj-$(CONFIG_CLK_BCM_KONA) += clk-kona-setup.o
 obj-$(CONFIG_CLK_BCM_KONA) += clk-bcm281xx.o
diff --git a/drivers/clk/bcm/clk-bcm6345.c b/drivers/clk/bcm/clk-bcm6345.c
new file mode 100644
index 000..88a1e7e
--- /dev/null
+++ b/drivers/clk/bcm/clk-bcm6345.c
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2015 Simon Arlott
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Derived from clk-gate.c:
+ * Copyright (C) 2010-2011 Canonical Ltd 
+ * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd 
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+/**
+ * DOC: Basic clock which uses a bit in a regmap to gate and ungate the output
+ *
+ * Traits of this clock:
+ * prepare - clk_(un)prepare only ensures parent is (un)prepared
+ * enable - clk_enable and clk_disable are functional & control gating
+ * rate - inherits rate from parent.  No clk_set_rate support
+ * parent - fixed parent.  No clk_set_parent support
+ */
+
+struct clk_bcm6345 {
+   struct clk_hw hw;
+   struct regmap *map;
+   u32 offset;
+   u32 mask;
+};
+
+#define to_clk_bcm6345(_hw) container_of(_hw, struct clk_bcm6345, hw)
+
+static int clk_bcm6345_enable(struct clk_hw *hw)
+{
+   struct clk_bcm6345 *gate = to_clk_bcm6345(hw);
+
+   return regmap_write_bits(gate->map, gate->offset,
+   gate->mask, gate->mask);
+}
+
+static void clk_bcm6345_disable(struct clk_hw *hw)
+{
+   struct clk_bcm6345 *gate = to_clk_bcm6345(hw);
+
+   regmap_write_bits(gate->map, gate->offset,
+   gate->mask, 0);
+}
+
+static int clk_bcm6345_is_enabled(struct clk_hw *hw)
+{
+   struct clk_bcm6345 *gate = to_clk_bcm6345(hw);
+   unsigned int val;
+   int ret;
+
+   ret = regmap_read(gate->map, gate->offset, &val);
+   if (ret)
+   return ret;
+
+   val &= gate->mask;
+
+   return val ? 1 : 0;
+}
+
+const struct clk_ops clk_bcm6345_ops = {
+   .enable = clk_bcm6345_enable,
+   .disable = clk_bcm6345_disable,
+   .is_enabled = clk_bcm6345_is_enabled,
+};
+
+static struct clk * __init of_bcm6345_clk_register(const char *parent_name,
+   const char *clk_name, struct regmap *map, u32 offset, u32 mask)
+{
+   struct clk_bcm6345 *gate;
+   struct clk_init_data init;
+   struc

[PATCH linux-next 1/2] clk: Add brcm,bcm6345-gate-clk device tree binding

2015-12-03 Thread Simon Arlott
Add device tree binding for the BCM6345's gated clocks.

The BCM6345 contains clocks gated with a register. Clocks are indexed
by bits in the register and are active high. Clock gate bits are
interleaved with other status bits and configurable clocks in the same
register.

Signed-off-by: Simon Arlott 
---
Renamed to BCM6345.

 .../bindings/clock/brcm,bcm6345-gate-clk.txt   | 58 ++
 1 file changed, 58 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/clock/brcm,bcm6345-gate-clk.txt

diff --git a/Documentation/devicetree/bindings/clock/brcm,bcm6345-gate-clk.txt 
b/Documentation/devicetree/bindings/clock/brcm,bcm6345-gate-clk.txt
new file mode 100644
index 000..5801264
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/brcm,bcm6345-gate-clk.txt
@@ -0,0 +1,58 @@
+Broadcom BCM6345 clocks
+
+This binding uses the common clock binding:
+   Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+The BCM6345 contains clocks gated with a register. Clocks are indexed
+by bits in the register and are active high. Clock gate bits are
+interleaved with other status bits and configurable clocks in the same
+register.
+
+Required properties:
+- compatible:  Should be "brcm,bcm-gate-clk", "brcm,bcm6345-gate-clk"
+- #clock-cells:Should be <1>.
+- regmap:  The register map phandle
+- offset:  Offset in the register map for the clock register (in bytes)
+- clocks:  The external oscillator clock phandle
+
+Example:
+
+periph_clk: periph_clk {
+   compatible = "brcm,bcm63168-gate-clk", "brcm,bcm6345-gate-clk";
+   regmap = <&periph_cntl>;
+   offset = <0x4>;
+
+   #clock-cells = <1>;
+   clock-indices =
+   <1>,  <2>,<3>,   <4>, <5>,
+   <6>,  <7>,<8>,   <9>, <10>,
+   <11>, <12>,   <13>,  <14>,<15>,
+   <16>, <17>,   <18>,  <19>,<20>,
+   <27>, <31>;
+   clock-output-names =
+   "vdsl_qproc", "vdsl_afe", "vdsl","mips",  "wlan_ocp",
+   "dect",   "fap0", "fap1","sar",   "robosw",
+   "pcm","usbd", "usbh","ipsec", "spi",
+   "hsspi",  "pcie", "phymips", "gmac",  "nand",
+   "tbus",   "robosw250";
+};
+
+timer_clk: timer_clk {
+   compatible = "brcm,bcm63168-gate-clk", "brcm,bcm6345-gate-clk";
+   regmap = <&timer_cntl>;
+   offset = <0x4>;
+
+   #clock-cells = <1>;
+   clock-indices = <17>, <18>;
+   clock-output-names = "uto_extin", "usb_ref";
+};
+
+ehci0: usb@10002500 {
+   compatible = "brcm,bcm63168-ehci", "brcm,bcm6345-ehci", "generic-ehci";
+   reg = <0x10002500 0x100>;
+   big-endian;
+   interrupt-parent = <&periph_intc>;
+   interrupts = <10>;
+   clocks = <&periph_clk 13>, <&timer_clk 18>;
+   phys = <&usbh>;
+};
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] regulator: Add brcm,bcm63xx-regulator device tree binding

2015-12-03 Thread Simon Arlott
On 03/12/15 00:06, Mark Brown wrote:
> On Wed, Dec 02, 2015 at 08:26:36PM +0000, Simon Arlott wrote:
>> On 02/12/15 12:53, Mark Brown wrote:
> 
>> > This is the sort of thing you can pick up from the SoC compatible
>> > strings.  As things stand there is zero content in this driver that
>> > relates to this SoC.
> 
>> There's always going to be very little content in the driver that
>> relates to this SoC, given that a single bit flip enables/disables
>> power.
> 
>> All other device tree drivers allow a register address to be specified
>> for the device, how is an offset in the regmap any different?
> 
> It's not that it's an offset in regmap, it's that you're trying to make
> a device driver with literally *no* content that is specific to the
> actual device.  If you're making a driver for a specific device like

The device that only has a single register, I don't want to make it
specific to the device by hard coding a register address in the driver
that changes when the same device is used on different SoCs.

> this it should know at least something about how to control the device
> from the compatible string.  If you're making a generic driver it should
> not make reference to specific devices.

Will you accept a generic driver for a simple enable regulator device on
a regmap? What should its compatible string be?

> In general I would prefer to have a driver with a SoC specific
> compatible string and the data tables in the kernel, that way we keep
> the device trees stable and our ABI more robust.
> 
>> >> The mask is used as there's one bit per regulator in the register, but
>> >> there's more than one way to express this in the DT:
> 
>> > I wouldn't expect to see it in the device tree at all for a device
>> > specific driver.
> 
>> If there isn't an individual entry in DT for each regulator, how is it
>> supposed to work? There's no #regulator-cells property.
> 
> There could be one if it would help, but we do normally manage to do
> this without - look at how other regulator drivers work.

Several of them have a fixed list of supported regulator names in the
driver. The regulator names for this device are meaningless to the
driver because all of the regulators look the same. They don't have a
known or controllable voltage and can only be turned on or off.

Any table mapping regulator names to bits in the register would be
different for each SoC making the list of regulator names in the device
tree redundant. If they're not listed in the device tree then I can't
use them as a phandle for other devices.

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 3/3] mtd: brcmnand: Add support for the BCM6368

2015-12-02 Thread Simon Arlott
The BCM6368 has a NAND interrupt register with combined status and enable
registers.

As the BCM6328, BCM6362 and BCM6368 all use v2.1 controllers, the first
variant that will work with this driver is the BCM63268 using a v4.0
controller.

Set up the device by disabling and acking all interrupts, then handle
the CTRL_READY interrupt.

Signed-off-by: Simon Arlott 
---
Renamed from BCM63268, moved clock to brcmnand.

 drivers/mtd/nand/brcmnand/Makefile   |   1 +
 drivers/mtd/nand/brcmnand/bcm6368_nand.c | 145 +++
 2 files changed, 146 insertions(+)
 create mode 100644 drivers/mtd/nand/brcmnand/bcm6368_nand.c

diff --git a/drivers/mtd/nand/brcmnand/Makefile 
b/drivers/mtd/nand/brcmnand/Makefile
index 3b1fbfd..b28ffb59 100644
--- a/drivers/mtd/nand/brcmnand/Makefile
+++ b/drivers/mtd/nand/brcmnand/Makefile
@@ -2,5 +2,6 @@
 # more specific iproc_nand.o, for instance
 obj-$(CONFIG_MTD_NAND_BRCMNAND)+= iproc_nand.o
 obj-$(CONFIG_MTD_NAND_BRCMNAND)+= bcm63138_nand.o
+obj-$(CONFIG_MTD_NAND_BRCMNAND)+= bcm6368_nand.o
 obj-$(CONFIG_MTD_NAND_BRCMNAND)+= brcmstb_nand.o
 obj-$(CONFIG_MTD_NAND_BRCMNAND)+= brcmnand.o
diff --git a/drivers/mtd/nand/brcmnand/bcm6368_nand.c 
b/drivers/mtd/nand/brcmnand/bcm6368_nand.c
new file mode 100644
index 000..c347ea5
--- /dev/null
+++ b/drivers/mtd/nand/brcmnand/bcm6368_nand.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright 2015 Simon Arlott
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * Derived from bcm63138_nand.c:
+ * Copyright © 2015 Broadcom Corporation
+ *
+ * Derived from 
bcm963xx_4.12L.06B_consumer/shared/opensource/include/bcm963xx/63268_map_part.h:
+ * Copyright 2000-2010 Broadcom Corporation
+ *
+ * Derived from 
bcm963xx_4.12L.06B_consumer/shared/opensource/flash/nandflash.c:
+ * Copyright 2000-2010 Broadcom Corporation
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "brcmnand.h"
+
+struct bcm6368_nand_soc {
+   struct brcmnand_soc soc;
+   void __iomem *base;
+};
+
+#define BCM6368_NAND_INT   0x00
+#define  BCM6368_NAND_STATUS_SHIFT 0
+#define  BCM6368_NAND_STATUS_MASK  (0xfff << BCM6368_NAND_STATUS_SHIFT)
+#define  BCM6368_NAND_ENABLE_SHIFT 16
+#define  BCM6368_NAND_ENABLE_MASK  (0x << BCM6368_NAND_ENABLE_SHIFT)
+#define BCM6368_NAND_BASE_ADDR00x04
+#define BCM6368_NAND_BASE_ADDR10x0c
+
+enum {
+   BCM6368_NP_READ = BIT(0),
+   BCM6368_BLOCK_ERASE = BIT(1),
+   BCM6368_COPY_BACK   = BIT(2),
+   BCM6368_PAGE_PGM= BIT(3),
+   BCM6368_CTRL_READY  = BIT(4),
+   BCM6368_DEV_RBPIN   = BIT(5),
+   BCM6368_ECC_ERR_UNC = BIT(6),
+   BCM6368_ECC_ERR_CORR= BIT(7),
+};
+
+static bool bcm6368_nand_intc_ack(struct brcmnand_soc *soc)
+{
+   struct bcm6368_nand_soc *priv =
+   container_of(soc, struct bcm6368_nand_soc, soc);
+   void __iomem *mmio = priv->base + BCM6368_NAND_INT;
+   u32 val = brcmnand_readl(mmio);
+
+   if (val & (BCM6368_CTRL_READY << BCM6368_NAND_STATUS_SHIFT)) {
+   /* Ack interrupt */
+   val &= ~BCM6368_NAND_STATUS_MASK;
+   val |= BCM6368_CTRL_READY << BCM6368_NAND_STATUS_SHIFT;
+   brcmnand_writel(val, mmio);
+   return true;
+   }
+
+   return false;
+}
+
+static void bcm6368_nand_intc_set(struct brcmnand_soc *soc, bool en)
+{
+   struct bcm6368_nand_soc *priv =
+   container_of(soc, struct bcm6368_nand_soc, soc);
+   void __iomem *mmio = priv->base + BCM6368_NAND_INT;
+   u32 val = brcmnand_readl(mmio);
+
+   /* Don't ack any interrupts */
+   val &= ~BCM6368_NAND_STATUS_MASK;
+
+   if (en)
+   val |= BCM6368_CTRL_READY << BCM6368_NAND_ENABLE_SHIFT;
+   else
+   val &= ~(BCM6368_CTRL_READY << BCM6368_NAND_ENABLE_SHIFT);
+
+   brcmnand_writel(val, mmio);
+}
+
+static int bcm6368_nand_probe(struct platform_device *pdev)
+{
+   struct device *dev = &pdev->dev;
+   struct bcm6368_nand_soc *priv;
+   struct brcmnand_soc *soc;
+   struct resource *res;
+
+   priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+   if (!priv)
+   return -ENOMEM;
+   soc = &priv->soc;
+
+   res = platform_get_resource_byname(pdev,
+   IORESOURCE_MEM, "nand-intr-base");
+

[PATCH 2/3] mtd: brcmnand: Request and enable the clock if present

2015-12-02 Thread Simon Arlott
Attempt to enable a clock named "nand" as some SoCs have a clock for the
controller that needs to be enabled.

Signed-off-by: Simon Arlott 
---
 drivers/mtd/nand/brcmnand/brcmnand.c | 69 
 1 file changed, 54 insertions(+), 15 deletions(-)

diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c 
b/drivers/mtd/nand/brcmnand/brcmnand.c
index 2c8f67f..0a9cccf 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
@@ -11,6 +11,7 @@
  * GNU General Public License for more details.
  */
 
+#include 
 #include 
 #include 
 #include 
@@ -122,6 +123,9 @@ struct brcmnand_controller {
/* Some SoCs provide custom interrupt status register(s) */
struct brcmnand_soc *soc;
 
+   /* Some SoCs have a gateable clock for the controller */
+   struct clk  *clk;
+
int cmd_pending;
booldma_pending;
struct completion   done;
@@ -2136,10 +2140,24 @@ int brcmnand_probe(struct platform_device *pdev, struct 
brcmnand_soc *soc)
if (IS_ERR(ctrl->nand_base))
return PTR_ERR(ctrl->nand_base);
 
+   /* Enable clock before using NAND registers */
+   ctrl->clk = devm_clk_get(dev, "nand");
+   if (!IS_ERR(ctrl->clk)) {
+   ret = clk_prepare_enable(ctrl->clk);
+   if (ret)
+   return ret;
+   } else {
+   ret = PTR_ERR(ctrl->clk);
+   if (ret == -EPROBE_DEFER)
+   return ret;
+
+   ctrl->clk = NULL;
+   }
+
/* Initialize NAND revision */
ret = brcmnand_revision_init(ctrl);
if (ret)
-   return ret;
+   goto err;
 
/*
 * Most chips have this cache at a fixed offset within 'nand' block.
@@ -2148,8 +2166,10 @@ int brcmnand_probe(struct platform_device *pdev, struct 
brcmnand_soc *soc)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand-cache");
if (res) {
ctrl->nand_fc = devm_ioremap_resource(dev, res);
-   if (IS_ERR(ctrl->nand_fc))
-   return PTR_ERR(ctrl->nand_fc);
+   if (IS_ERR(ctrl->nand_fc)) {
+   ret = PTR_ERR(ctrl->nand_fc);
+   goto err;
+   }
} else {
ctrl->nand_fc = ctrl->nand_base +
ctrl->reg_offsets[BRCMNAND_FC_BASE];
@@ -2159,8 +2179,10 @@ int brcmnand_probe(struct platform_device *pdev, struct 
brcmnand_soc *soc)
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "flash-dma");
if (res) {
ctrl->flash_dma_base = devm_ioremap_resource(dev, res);
-   if (IS_ERR(ctrl->flash_dma_base))
-   return PTR_ERR(ctrl->flash_dma_base);
+   if (IS_ERR(ctrl->flash_dma_base)) {
+   ret = PTR_ERR(ctrl->flash_dma_base);
+   goto err;
+   }
 
flash_dma_writel(ctrl, FLASH_DMA_MODE, 1); /* linked-list */
flash_dma_writel(ctrl, FLASH_DMA_ERROR_STATUS, 0);
@@ -2169,13 +2191,16 @@ int brcmnand_probe(struct platform_device *pdev, struct 
brcmnand_soc *soc)
ctrl->dma_desc = dmam_alloc_coherent(dev,
 sizeof(*ctrl->dma_desc),
 &ctrl->dma_pa, GFP_KERNEL);
-   if (!ctrl->dma_desc)
-   return -ENOMEM;
+   if (!ctrl->dma_desc) {
+   ret = -ENOMEM;
+   goto err;
+   }
 
ctrl->dma_irq = platform_get_irq(pdev, 1);
if ((int)ctrl->dma_irq < 0) {
dev_err(dev, "missing FLASH_DMA IRQ\n");
-   return -ENODEV;
+   ret = -ENODEV;
+   goto err;
}
 
ret = devm_request_irq(dev, ctrl->dma_irq,
@@ -2184,7 +2209,7 @@ int brcmnand_probe(struct platform_device *pdev, struct 
brcmnand_soc *soc)
if (ret < 0) {
dev_err(dev, "can't allocate IRQ %d: error %d\n",
ctrl->dma_irq, ret);
-   return ret;
+   goto err;
}
 
dev_info(dev, "enabling FLASH_DMA\n");
@@ -2208,7 +2233,8 @@ int brcmnand_probe(struct platform_device *pdev, struct 
brcmnand_soc *soc)
ctrl->irq = platform_get_irq(pdev, 0);
if ((int)ctrl->irq < 0) {
dev_err(dev, "no IRQ defined\n");
-   return -ENODEV;
+   ret = -ENODEV;
+   

[PATCH 1/3] mtd: brcmnand: Add brcm,bcm6368-nand device tree binding

2015-12-02 Thread Simon Arlott
Add device tree binding for NAND on the BCM6368.

The BCM6368 has a NAND interrupt register with combined status and enable
registers. It also requires a clock, so add an optional clock to the
common brcmnand binding.

Signed-off-by: Simon Arlott 
---
Renamed from BCM63268, made clock a generic property.

 .../devicetree/bindings/mtd/brcm,brcmnand.txt  | 32 ++
 1 file changed, 32 insertions(+)

diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt 
b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
index 4ff7128..16d7835 100644
--- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
+++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
@@ -45,6 +45,8 @@ Required properties:
 - #size-cells  : <0>
 
 Optional properties:
+- clock : reference to the clock for the NAND controller
+- clock-names   : "nand" (required for the above clock)
 - brcm,nand-has-wp  : Some versions of this IP include a write-protect
   (WP) control bit. It is always available on >=
   v7.0. Use this property to describe the rare
@@ -72,6 +74,12 @@ we define additional 'compatible' properties and associated 
register resources w
and enable registers
  - reg-names: (required) "nand-int-base"
 
+   * "brcm,nand-bcm6368"
+ - compatible: should contain "brcm,nand-bcm", "brcm,nand-bcm6368"
+ - reg: (required) the 'NAND_INTR_BASE' register range, with combined 
status
+   and enable registers, and boot address registers
+ - reg-names: (required) "nand-intr-base"
+
* "brcm,nand-iproc"
  - reg: (required) the "IDM" register range, for interrupt enable and APB
bus access endianness configuration, and the "EXT" register range,
@@ -148,3 +156,27 @@ nand@f0442800 {
};
};
 };
+
+nand@1200 {
+   compatible = "brcm,nand-bcm63168", "brcm,nand-bcm6368",
+   "brcm,brcmnand-v4.0", "brcm,brcmnand";
+   reg = <0x1200 0x180>,
+ <0x1600 0x200>,
+ <0x10b0 0x10>;
+   reg-names = "nand", "nand-cache", "nand-intr-base";
+   interrupt-parent = <&periph_intc>;
+   interrupts = <50>;
+   clocks = <&periph_clk 20>;
+   clock-names = "nand";
+
+   #address-cells = <1>;
+   #size-cells = <0>;
+
+   nand0: nandcs@0 {
+   compatible = "brcm,nandcs";
+   reg = <0>;
+   nand-on-flash-bbt;
+   nand-ecc-strength = <1>;
+   nand-ecc-step-size = <512>;
+   };
+};
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] mtd: brcmnand: Workaround false ECC uncorrectable errors

2015-12-02 Thread Simon Arlott
On 02/12/15 21:08, Jonas Gorski wrote:
> On Wed, Dec 2, 2015 at 9:54 PM, Brian Norris
>  wrote:
>>
>> BTW, I think Kamal had code to handle protecting bitflips in erased
>> pages code in the Broadcom STB Linux BSP. Perhaps he can port that to
>> upstream with nand_check_erased_ecc_chunk()? IIUC, that would probably
>> handle your case too, Simon, although it wouldn't be optimal for an
>> all-0xff check (i.e., bitflip_threshold == 0).
>>
>> If that's really an issue (i.e., we have an implementation + data), I'm
>> sure we could add optimization to nand_check_erased_ecc_chunk() to
>> support the bitflip_threshold == 0 case.
> 
> Maybe I'm missing something, but wasn't the point of introducing
> nand_check_erased_ecc_chunk that bitflips in erased pages should be
> treated as bitflips corrected by the ecc, and therefore fixed up
> before passing the data further on? So having a theshold of 0 would be
> wrong / no protection at all, and could be quite destructive on MLC
> nand, where bitflips in erased pages are rather common.

Without this patch I can't access erased pages at all. I don't know if
the controller will still return an uncorrectable error if the page is
erased but has 1 or more bit flips.

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH (v2) 2/2] reset: bcm6345: Add support for the BCM6345 soft-reset controller

2015-12-02 Thread Simon Arlott
The BCM6345 contains a soft-reset controller activated by setting
a bit (that must previously have cleared).

Signed-off-by: Simon Arlott 
---
 MAINTAINERS   |   1 +
 drivers/reset/Kconfig |   1 +
 drivers/reset/Makefile|  17 +++---
 drivers/reset/bcm/Kconfig |  10 
 drivers/reset/bcm/Makefile|   1 +
 drivers/reset/bcm/reset-bcm6345.c | 109 ++
 6 files changed, 131 insertions(+), 8 deletions(-)
 create mode 100644 drivers/reset/bcm/Kconfig
 create mode 100644 drivers/reset/bcm/Makefile
 create mode 100644 drivers/reset/bcm/reset-bcm6345.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 07613dd..a20cecf 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2378,6 +2378,7 @@ F:drivers/irqchip/irq-bcm63*
 F: drivers/irqchip/irq-bcm7*
 F: drivers/irqchip/irq-brcmstb*
 F: drivers/regulator/bcm63*
+F: drivers/reset/bcm/reset-bcm6345*
 F: include/linux/bcm63xx_wdt.h
 
 BROADCOM TG3 GIGABIT ETHERNET DRIVER
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 0615f50..ee73f5f 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -12,4 +12,5 @@ menuconfig RESET_CONTROLLER
 
  If unsure, say no.
 
+source "drivers/reset/bcm/Kconfig"
 source "drivers/reset/sti/Kconfig"
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 85d5904..a34f469 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -1,8 +1,9 @@
-obj-$(CONFIG_RESET_CONTROLLER) += core.o
-obj-$(CONFIG_ARCH_LPC18XX) += reset-lpc18xx.o
-obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
-obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
-obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
-obj-$(CONFIG_ARCH_STI) += sti/
-obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o
-obj-$(CONFIG_ATH79) += reset-ath79.o
+obj-$(CONFIG_RESET_CONTROLLER) += core.o
+obj-$(CONFIG_ARCH_LPC18XX) += reset-lpc18xx.o
+obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
+obj-$(CONFIG_ARCH_BERLIN)  += reset-berlin.o
+obj-$(CONFIG_ARCH_SUNXI)   += reset-sunxi.o
+obj-$(CONFIG_ARCH_STI) += sti/
+obj-$(CONFIG_ARCH_ZYNQ)+= reset-zynq.o
+obj-$(CONFIG_ATH79)+= reset-ath79.o
+obj-y  += bcm/
diff --git a/drivers/reset/bcm/Kconfig b/drivers/reset/bcm/Kconfig
new file mode 100644
index 000..85931c9
--- /dev/null
+++ b/drivers/reset/bcm/Kconfig
@@ -0,0 +1,10 @@
+if RESET_CONTROLLER
+
+config RESET_BCM6345
+   bool "BCM6345 Reset Controller"
+   depends on BMIPS_GENERIC
+   default BMIPS_GENERIC
+   help
+ Support resetting of devices on BCM6345 boards.
+
+endif
diff --git a/drivers/reset/bcm/Makefile b/drivers/reset/bcm/Makefile
new file mode 100644
index 000..3d004bd
--- /dev/null
+++ b/drivers/reset/bcm/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_RESET_BCM6345)+= reset-bcm6345.o
diff --git a/drivers/reset/bcm/reset-bcm6345.c 
b/drivers/reset/bcm/reset-bcm6345.c
new file mode 100644
index 000..a95433d
--- /dev/null
+++ b/drivers/reset/bcm/reset-bcm6345.c
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2015 Simon Arlott
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * Derived from reset-berlin.c:
+ * Copyright (C) 2014 Marvell Technology Group Ltd.
+ *
+ * Antoine Tenart 
+ * Sebastian Hesselbarth 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define to_bcm6345_reset_priv(p) \
+   container_of((p), struct bcm6345_reset_priv, rcdev)
+
+struct bcm6345_reset_priv {
+   struct regmap *map;
+   u32 offset;
+   struct reset_controller_dev rcdev;
+   struct mutex mutex;
+};
+
+static int bcm6345_reset_reset(struct reset_controller_dev *rcdev,
+   unsigned long id)
+{
+   struct bcm6345_reset_priv *priv = to_bcm6345_reset_priv(rcdev);
+
+   mutex_lock(&priv->mutex);
+   regmap_write_bits(priv->map, priv->offset, BIT(id), 0);
+   usleep_range(1, 2);
+   regmap_write_bits(priv->map, priv->offset, BIT(id), BIT(id));
+   usleep_range(1, 2);
+   mutex_unlock(&priv->mutex);
+
+   return 0;
+}
+
+static struct reset_control_ops bcm6345_reset_ops = {
+   .reset = bcm6345_reset_reset,
+};
+
+static int __init bcm6345_reset_probe(struct platform_device *pdev)
+{
+   struct device_node *np = pdev->dev.of_node;
+   struct bcm6345_reset_priv *priv;
+   int ret;
+
+   priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+   if (!priv)
+   return -ENOMEM;
+
+   mutex_init(&priv->mutex);
+
+   priv->map = syscon_regmap_lookup_by_phandle(np, "regmap");
+   if (IS_ERR(priv->map))
+   return PTR_ERR(

[PATCH (v2) 1/2] reset: Add brcm,bcm6345-reset device tree binding

2015-12-02 Thread Simon Arlott
Add device tree binding for the BCM6345 soft reset controller.

The BCM6345 contains a soft-reset controller activated by setting
a bit (that must previously have cleared).

Signed-off-by: Simon Arlott 
---
Renamed to bcm6345, removed "mask" property.

 .../bindings/reset/brcm,bcm6345-reset.txt  | 33 ++
 1 file changed, 33 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/reset/brcm,bcm6345-reset.txt

diff --git a/Documentation/devicetree/bindings/reset/brcm,bcm6345-reset.txt 
b/Documentation/devicetree/bindings/reset/brcm,bcm6345-reset.txt
new file mode 100644
index 000..bb9ca6e
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/brcm,bcm6345-reset.txt
@@ -0,0 +1,33 @@
+Broadcom BCM6345 reset controller
+
+The BCM6345 contains a basic soft reset controller in the perf register
+set which resets components using a bit in a register.
+
+Please also refer to reset.txt in this directory for common reset
+controller binding usage.
+
+Required properties:
+- compatible:  Should be "brcm,bcm-reset", "brcm,bcm6345-reset"
+- regmap:  The register map phandle
+- offset:  Offset in the register map for the reset register (in bytes)
+- #reset-cells:Must be set to 1
+
+Example:
+
+periph_soft_rst: reset-controller {
+   compatible = "brcm,bcm63168-reset", "brcm,bcm6345-reset";
+   regmap = <&periph_cntl>;
+   offset = <0x10>;
+
+   #reset-cells = <1>;
+};
+
+usbh: usbphy@10002700 {
+   compatible = "brcm,bcm63168-usbh";
+   reg = <0x10002700 0x38>;
+   clocks = <&periph_clk 13>, <&timer_clk 18>;
+   resets = <&periph_soft_rst 6>;
+   power-supply = <&power_usbh>;
+   #phy-cells = <0>;
+};
+
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 2/2] reset: bcm63xx: Add support for the BCM63xx soft-reset controller

2015-12-02 Thread Simon Arlott
On 02/12/15 18:03, Florian Fainelli wrote:
> 2015-11-30 12:58 GMT-08:00 Simon Arlott :
>> The BCM63xx contains a soft-reset controller activated by setting
>> a bit (that must previously have cleared).
>>
>> Signed-off-by: Simon Arlott 
>> ---
>>  MAINTAINERS   |   1 +
>>  drivers/reset/Kconfig |   9 +++
>>  drivers/reset/Makefile|   1 +
>>  drivers/reset/reset-bcm63xx.c | 134 
>> ++
>>  4 files changed, 145 insertions(+)
>>  create mode 100644 drivers/reset/reset-bcm63xx.c
> 
> 
> Could you create a bcm directory and then add your reset-bcm63xx.c
> file there? I have a pending submission for the BCM63138 reset
> controller which is not at all using the same structure and will share
> nothing with your driver.
> 

Ok, I'll call it reset-bcm6345.c to avoid confusion.

> 
>> +static int bcm63xx_reset_xlate(struct reset_controller_dev *rcdev,
>> +   const struct of_phandle_args *reset_spec)
>> +{
>> +   struct bcm63xx_reset_priv *priv = to_bcm63xx_reset_priv(rcdev);
>> +
>> +   if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells))
>> +   return -EINVAL;
>> +
>> +   if (reset_spec->args[0] >= rcdev->nr_resets)
>> +   return -EINVAL;
> 
> Should not these two things be moved to the core reset controller code
> based on the #reset-cells value?
> 

This has already been removed from the next version of the patch.

> 
>> +   if (of_property_read_u32(np, "offset", &priv->offset))
>> +   return -EINVAL;
>> +
>> +   /* valid reset bits */
>> +   if (of_property_read_u32(np, "mask", &priv->mask))
>> +   priv->mask = 0x;
>> +
>> +   priv->rcdev.owner = THIS_MODULE;
>> +   priv->rcdev.ops = &bcm63xx_reset_ops;
>> +   priv->rcdev.nr_resets = 32;
> 
> Should not that come from Device Tree, or be computed based on the
> mask property, like hweight_long() or something along these lines?

The "mask" property has been removed. It will assume 32 resets and rely
on the rest of the DT to only refer to valid bits.

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH (v6) 1/2] mtd: brcmnand: Add brcm,bcm63268-nand device tree binding

2015-12-02 Thread Simon Arlott
On 02/12/15 20:21, Brian Norris wrote:
> Hi Simon,
> 
> On Wed, Dec 02, 2015 at 08:12:32PM +0000, Simon Arlott wrote:
>> On 02/12/15 20:00, Brian Norris wrote:
>> > On Wed, Dec 02, 2015 at 07:41:07PM +, Simon Arlott wrote:
>> >> I've created a bcm963268part driver so there won't need to be any
>> >> partitions in DT for bcm63268.
>> > 
>> > Just curious, do you plan to submit this driver? We're working on
>> 
>> Yes, it's just the most recent one I've been working on. I still have
>> USBH and IUDMA to submit
>> 
>> > matching up partition parsers to flash devices via device tree
>> > of_match_table's, so you could do something like this:
>> > 
>> >nand0: nandcs@0 {
>> >compatible = "brcm,nandcs";
>> >...
>> > 
>> >partitions {
>> >compatible = "brcm,bcm963268-partitions";
>> >...
>> >};
>> >};
>> 
>> I modified brcmnand to look for a machine matching "brcm,bcm963268", but
> 
> Like this?
> 
> http://patchwork.ozlabs.org/patch/473180/
> 
> I'd like to avoid that (hence the "Rejected" status).

I exported default_mtd_part_types, copied it, and then added to it:
+   for (i = 0; i < nr_types; i++)
+   part_types[i] = default_mtd_part_types[i];
+
+   /* Add partition type based on machine */
+   if (of_machine_is_compatible("brcm,bcm963268"))
+   part_types[i++] = "bcm963268part";
+   else
+   part_types[i++] = NULL;
+
+   part_types[i++] = NULL;

>> that way is ok with me. Presumably "ofpart" defers to another matching
>> partition parser?
> 
> Yes, "ofpart" is for specifying the entire partition table in the device
> tree as subnodes of either the flash node or of the flash's "partitions"
> subnode. It's not the most flexible, but it does work generically.
> 
>> Is there a patch for that method of parser detection available?
> 
> I have something working here, but I haven't had time to finish cleaning
> it up and submitting it. There's an older patch that works similarly,
> though it has some deficiencies:
> 
> http://patchwork.ozlabs.org/patch/475988/
> 
> The main difference between that and my (yet-to-be-submitted) proposal
> is that I'd like parsers to opt in by adding a proper of_match_table
> with non-Linux-specific DT bindings, and then we can drop the
> "linux,..." naming and make it a reasonably generic property.

I'll submit my parser without any means of using it, let me know if you
want me to work on a patch for a match table.

> Regards,
> Brian
> 


-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] regulator: Add brcm,bcm63xx-regulator device tree binding

2015-12-02 Thread Simon Arlott
On 02/12/15 12:53, Mark Brown wrote:
> On Wed, Dec 02, 2015 at 12:45:50PM -0000, Simon Arlott wrote:
>> On Tue, December 1, 2015 22:16, Mark Brown wrote:
> 
>> > Why are these in the DT, I would expect that if this is a driver for a
>> > specific SoC all these properties would be known as a result of that.
> 
>> This is a driver for multiple SoCs with the same regulator control in
>> different places on different SoCs, so the location of it within the misc
>> register needs to be provided in the DT:
> 
>> BCM6362:
>>   #define MISC_BASE 0xb0001800 /* Miscellaneous Registers */
>>   uint32 miscIddqCtrl; /* 0x48 */
> 
> This is the sort of thing you can pick up from the SoC compatible
> strings.  As things stand there is zero content in this driver that
> relates to this SoC.

There's always going to be very little content in the driver that
relates to this SoC, given that a single bit flip enables/disables
power.

All other device tree drivers allow a register address to be specified
for the device, how is an offset in the regmap any different?

>> The mask is used as there's one bit per regulator in the register, but
>> there's more than one way to express this in the DT:
> 
> I wouldn't expect to see it in the device tree at all for a device
> specific driver.

If there isn't an individual entry in DT for each regulator, how is it
supposed to work? There's no #regulator-cells property.

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH] mtd: brcmnand: Workaround false ECC uncorrectable errors

2015-12-02 Thread Simon Arlott
On 01/12/15 10:41, Jonas Gorski wrote:
> On Sat, Nov 28, 2015 at 8:23 PM, Simon Arlott  wrote:
>> +
>> +   /* Go to start of buffer */
>> +   buf -= FC_WORDS;
>> +
>> +   /* Erased if all data bytes are 0xFF */
>> +   buf_erased = memchr_inv(buf, 0xFF, FC_WORDS) == NULL;
>> +
>> +   if (!buf_erased)
>> +   goto out_free;
> 
> We now have a function exactly for that use case in 4.4,
> nand_check_erased_buf [1], consider using that. This also has the
> benefit of treating bit flips as correctable as long as the ECC scheme
> is strong enough.

I have no idea whether or not it's appropriate to specify
bitflips_threshold > 0 so it'd just be a more complex way to do
a memchr_inv() search for 0xFF.

The code also has to check for the hamming code bytes being all 0x00,
because according to the comments [2], the controller also has
difficulty with the non-erased all-0xFFs scenario too.

[2] 
https://github.com/lp0/bcm963xx_4.12L.06B_consumer/blob/dd8fcb13046f738c311507dc2fcfd3e5d57a88e0/kernel/linux/drivers/mtd/brcmnand/brcmnand_base.c#L2459

> 
> Jonas
> 
> [1] 
> https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/mtd/nand/nand_base.c#n1110
> 

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH (v6) 1/2] mtd: brcmnand: Add brcm,bcm63268-nand device tree binding

2015-12-02 Thread Simon Arlott
On 02/12/15 20:00, Brian Norris wrote:
> Hi,
> 
> On Wed, Dec 02, 2015 at 07:41:07PM +0000, Simon Arlott wrote:
>> >> + nand0: nandcs@0 {
>> >> + compatible = "brcm,nandcs";
>> >> +
>> >> + #address-cells = <0>;
>> >> + #size-cells = <0>;
> 
>> I think they're also implicit so you can just remove those two lines.
> 
> From ePAPR: "The #address-cells and #size-cells properties are not
> inherited from ancestors in the device tree. They shall be explicitly
> defined."
> 
> But we don't want to define them. I'd drop them, at least from the
> example, as they're not relevant.

Ok.

>> I've created a bcm963268part driver so there won't need to be any
>> partitions in DT for bcm63268.
> 
> Just curious, do you plan to submit this driver? We're working on

Yes, it's just the most recent one I've been working on. I still have
USBH and IUDMA to submit

> matching up partition parsers to flash devices via device tree
> of_match_table's, so you could do something like this:
> 
>   nand0: nandcs@0 {
>   compatible = "brcm,nandcs";
>   ...
> 
>   partitions {
>   compatible = "brcm,bcm963268-partitions";
>   ...
>   };
>   };

I modified brcmnand to look for a machine matching "brcm,bcm963268", but
that way is ok with me. Presumably "ofpart" defers to another matching
partition parser?

Is there a patch for that method of parser detection available?

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH (v6) 1/2] mtd: brcmnand: Add brcm,bcm63268-nand device tree binding

2015-12-02 Thread Simon Arlott
On 02/12/15 19:38, Florian Fainelli wrote:
> 2015-12-02 11:05 GMT-08:00 Brian Norris :
>> + Broadcom list + Kamal
>>
>> On Tue, Nov 24, 2015 at 08:19:37PM -, Simon Arlott wrote:
>>> Add device tree binding for NAND on the BCM63268.
>>>
>>> The BCM63268 has a NAND interrupt register with combined status and enable
>>> registers.
>>>
>>> Signed-off-by: Simon Arlott 
>>> ---
>>>  .../devicetree/bindings/mtd/brcm,brcmnand.txt  | 35 
>>> ++
>>>  1 file changed, 35 insertions(+)
>>>
>>> diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
>>> b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
>>> index 4ff7128..f2a71c8 100644
>>> --- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
>>> +++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
>>> @@ -72,6 +72,14 @@ we define additional 'compatible' properties and 
>>> associated register resources w
>>> and enable registers
>>>   - reg-names: (required) "nand-int-base"
>>>
>>> +   * "brcm,nand-bcm63268"
>>> + - compatible: should contain "brcm,nand-bcm", 
>>> "brcm,nand-bcm63268"
>>
>> Looks like you're aiming to support bcm63168? Is bcm63268 the first
>> chip to include this style of register then? The numbering seems
>> backwards, but that may just be reality.
> 
> 6362 (NAND rev 2.1, ann. Sep 8, 2009), 6368 (v0.1?!?, ann. Jan 7,
> 2009) and 6328 (v2.1, can't find release date) are earlier chips that
> have an identical combined interrupt enable + status register and a
> NAND controller within the same 32-bits word, so these would qualify
> as a better compatible string for this specific addition integration
> stub here. I would gowith 6368 here then?
> 

I could change it to 6368 but there's no documented NAND_INTR_BASE for
it. Only the 63268 and 6818 have a #define for NAND_INTR_BASE.

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH (v7) 2/2] mtd: brcmnand: Add support for the BCM63268

2015-12-02 Thread Simon Arlott
On 02/12/15 19:18, Brian Norris wrote:
> + Broadcom list + Kamal
> 
> Hi Simon,
> 
> On Wed, Nov 25, 2015 at 07:49:13PM +0000, Simon Arlott wrote:
>> The BCM63268 has a NAND interrupt register with combined status and enable
>> registers. It also has a clock for the NAND controller that needs to be
>> enabled.
>> 
>> Set up the device by enabling the clock, disabling and acking all
>> interrupts, then handle the CTRL_READY interrupt.
>> 
>> Add a brcmnand_get_socdata() function so that bcm63268_nand can obtain its
>> data and disable the clock when the device is removed.
>> 
>> Signed-off-by: Simon Arlott 
>> ---
>> Added EXPORT_SYMBOL_GPL(brcmnand_get_socdata)
>> 
>> (As the brcmnand module must be loaded first its compatible string will
>> apply to any existing devices before the soc-specific module can be
>> loaded.)
> 
> What's this comment supposed to mean? The brcmnand module will not
> directly probe any devices. It doesn't register any driver structs by
> itself.

I didn't notice that it didn't actually probe devices. In that case the
documentation should not require "brcm,brcmnand" for soc-specific
variants because the hardware's not really compatible with it.

> (BTW given that, it probably doesn't need its MODULE_DEVICE_TABLE.)
> 
>>  drivers/mtd/nand/brcmnand/Makefile|   1 +
>>  drivers/mtd/nand/brcmnand/bcm63268_nand.c | 179 
>> ++
>>  drivers/mtd/nand/brcmnand/brcmnand.c  |   8 ++
>>  drivers/mtd/nand/brcmnand/brcmnand.h  |   1 +
>>  4 files changed, 189 insertions(+)
>>  create mode 100644 drivers/mtd/nand/brcmnand/bcm63268_nand.c
>> 
>> diff --git a/drivers/mtd/nand/brcmnand/Makefile 
>> b/drivers/mtd/nand/brcmnand/Makefile
>> index 3b1fbfd..b83a9ae 100644
>> --- a/drivers/mtd/nand/brcmnand/Makefile
>> +++ b/drivers/mtd/nand/brcmnand/Makefile
>> @@ -2,5 +2,6 @@
>>  # more specific iproc_nand.o, for instance
>>  obj-$(CONFIG_MTD_NAND_BRCMNAND) += iproc_nand.o
>>  obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63138_nand.o
>> +obj-$(CONFIG_MTD_NAND_BRCMNAND) += bcm63268_nand.o
>>  obj-$(CONFIG_MTD_NAND_BRCMNAND) += brcmstb_nand.o
>>  obj-$(CONFIG_MTD_NAND_BRCMNAND)     += brcmnand.o
>> diff --git a/drivers/mtd/nand/brcmnand/bcm63268_nand.c 
>> b/drivers/mtd/nand/brcmnand/bcm63268_nand.c
>> new file mode 100644
>> index 000..70ad907
>> --- /dev/null
>> +++ b/drivers/mtd/nand/brcmnand/bcm63268_nand.c
>> @@ -0,0 +1,179 @@
>> +/*
>> + * Copyright 2015 Simon Arlott
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>> + * GNU General Public License for more details.
>> + *
>> + * Derived from bcm63138_nand.c:
>> + * Copyright © 2015 Broadcom Corporation
>> + *
>> + * Derived from 
>> bcm963xx_4.12L.06B_consumer/shared/opensource/include/bcm963xx/63268_map_part.h:
>> + * Copyright 2000-2010 Broadcom Corporation
>> + *
>> + * Derived from 
>> bcm963xx_4.12L.06B_consumer/shared/opensource/flash/nandflash.c:
>> + * Copyright 2000-2010 Broadcom Corporation
>> + */
>> +
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +#include 
>> +
>> +#include "brcmnand.h"
>> +
>> +struct bcm63268_nand_soc {
>> +struct brcmnand_soc soc;
>> +void __iomem *base;
>> +struct clk *clk;
>> +};
>> +
>> +#define BCM63268_NAND_INT   0x00
>> +#define  BCM63268_NAND_STATUS_SHIFT 0
>> +#define  BCM63268_NAND_STATUS_MASK  (0xfff << BCM63268_NAND_STATUS_SHIFT)
>> +#define  BCM63268_NAND_ENABLE_SHIFT 16
>> +#define  BCM63268_NAND_ENABLE_MASK  (0x << BCM63268_NAND_ENABLE_SHIFT)
>> +#define BCM63268_NAND_BASE_ADDR00x04
>> +#define BCM63268_NAND_BASE_ADDR10x0c
>> +
>> +enum {
>> +BCM63268_NP_READ= BIT(0),
>> +BCM63268_BLOCK_ERASE= BIT(1),
>> +BCM63268_COPY_BACK  = BIT(2),
>> +BCM63268_PAGE_PGM   = BIT(3),
>> +BCM63268_CTRL_READY = BIT(4),
>> +

Re: [PATCH (v6) 1/2] mtd: brcmnand: Add brcm,bcm63268-nand device tree binding

2015-12-02 Thread Simon Arlott
On 02/12/15 19:05, Brian Norris wrote:
> + Broadcom list + Kamal
> 
> On Tue, Nov 24, 2015 at 08:19:37PM -0000, Simon Arlott wrote:
>> Add device tree binding for NAND on the BCM63268.
>> 
>> The BCM63268 has a NAND interrupt register with combined status and enable
>> registers.
>> 
>> Signed-off-by: Simon Arlott 
>> ---
>>  .../devicetree/bindings/mtd/brcm,brcmnand.txt  | 35 
>> ++
>>  1 file changed, 35 insertions(+)
>> 
>> diff --git a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
>> b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
>> index 4ff7128..f2a71c8 100644
>> --- a/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
>> +++ b/Documentation/devicetree/bindings/mtd/brcm,brcmnand.txt
>> @@ -72,6 +72,14 @@ we define additional 'compatible' properties and 
>> associated register resources w
>> and enable registers
>>   - reg-names: (required) "nand-int-base"
>> 
>> +   * "brcm,nand-bcm63268"
>> + - compatible: should contain "brcm,nand-bcm", "brcm,nand-bcm63268"
> 
> Looks like you're aiming to support bcm63168? Is bcm63268 the first
> chip to include this style of register then? The numbering seems
> backwards, but that may just be reality.

Yes, I have a BCM963168VX (BCM63168) but all the Broadcom code refers to
this SoC as BCM63268. This is the only one with these registers in the
source code of similar MIPS that I have.


https://github.com/lp0/bcm963xx_4.12L.06B_consumer/blob/master/bcmdrivers/opensource/char/board/bcm963xx/impl1/board.c#L6595

int kerSysGetChipId() {
...
/* Force BCM63168, BCM63169, and BCM63269 to be BCM63268) */
if( ( (r & 0xe) == 0x63168 )
  || ( (r & 0xe) == 0x63268 ))
r = 0x63268;

>> + - reg: (required) the 'NAND_INTR_BASE' register range, with combined 
>> status
>> +   and enable registers, and boot address registers
>> + - reg-names: (required) "nand-intr-base"
>> + - clock: (required) reference to the clock for the NAND controller
>> + - clock-names: (required) "nand"
>> +
>> * "brcm,nand-iproc"
>>   - reg: (required) the "IDM" register range, for interrupt enable and 
>> APB
>> bus access endianness configuration, and the "EXT" register range,
>> @@ -148,3 +156,30 @@ nand@f0442800 {
>>  };
>>  };
>>  };
>> +
>> +nand@1200 {
>> +compatible = "brcm,nand-bcm63168", "brcm,nand-bcm63268",
>> +"brcm,brcmnand-v4.0", "brcm,brcmnand";
>> +reg = <0x1200 0x180>,
>> +  <0x1600 0x200>,
>> +  <0x10b0 0x10>;
>> +reg-names = "nand", "nand-cache", "nand-intr-base";
>> +interrupt-parent = <&periph_intc>;
>> +interrupts = <50>;
>> +clocks = <&periph_clk 20>;
>> +clock-names = "nand";
>> +
>> +#address-cells = <1>;
>> +#size-cells = <0>;
>> +
>> +nand0: nandcs@0 {
>> +compatible = "brcm,nandcs";
>> +reg = <0>;
>> +nand-on-flash-bbt;
>> +nand-ecc-strength = <1>;
>> +nand-ecc-step-size = <512>;
>> +
>> +#address-cells = <0>;
>> +#size-cells = <0>;
> 
> What are these {address,size}-cells for? If you need them for
> partitioning, then those are wrong -- they shouldn't be zero. Maybe just
> drop them? (I can cut them out when applying, if that's the only change
> to make.)

This is the correct way to do partitioning, there would be a
"partitions" block with no address/size that contains the partitions as
child nodes. [Documentation/devicetree/bindings/mtd/partition.txt]

I think they're also implicit so you can just remove those two lines.

I've created a bcm963268part driver so there won't need to be any
partitions in DT for bcm63268.

>> +};
>> +};
> 
> Brian
> 


-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCH 1/2] regulator: Add brcm,bcm63xx-regulator device tree binding

2015-12-02 Thread Simon Arlott
On Tue, December 1, 2015 22:16, Mark Brown wrote:
> On Mon, Nov 30, 2015 at 08:30:07PM +0000, Simon Arlott wrote:
>
>> +- offset: register offset
>> +- mask: register enable mask
>> +- startup-delay-us: startup time in microseconds
>
> Why are these in the DT, I would expect that if this is a driver for a
> specific SoC all these properties would be known as a result of that.

This is a driver for multiple SoCs with the same regulator control in
different places on different SoCs, so the location of it within the misc
register needs to be provided in the DT:

BCM6362:
  #define MISC_BASE 0xb0001800 /* Miscellaneous Registers */
  uint32 miscIddqCtrl; /* 0x48 */

BCM63268/BCM63168:
  #define MISC_BASE 0xb0001800 /* Miscellaneous Registers */
  uint32 miscIddqCtrl; /* 0x4c */


I'll remove the startup-delay-us property and put a default in the driver.


The mask is used as there's one bit per regulator in the register, but
there's more than one way to express this in the DT:

It currently looks like this:
  regulators {
compatible = "simple-bus";
#address-cells = <0>;
#size-cells = <0>;

sar {
  compatible = "brcm,bcm63168-regulator", "brcm,bcm6345-regulator";
  regulator-name = "sar_power";
  regmap = <&misc>;
  offset = <0x4c>;
  mask = <0x1>;
  startup-delay-us = <10>;
};

ipsec {
  compatible = "brcm,bcm63168-regulator", "brcm,bcm6345-regulator";
  regulator-name = "ipsec_power";
  regmap = <&misc>;
  offset = <0x4c>;
  mask = <0x2>;
  startup-delay-us = <10>;
};

...
  };

  ubus {
compatible = "brcm,ubus", "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges;

misc: syscon@10001800 {
  compatible = "syscon";
  reg = <0x10001800 0xd0>;
};
  };

Would this be more appropriate?
  regulators {
compatible = "simple-bus";
#address-cells = <0>;
#size-cells = <0>;

misc_iddq_ctrl {
  compatible = "brcm,bcm63168-regulator", "brcm,bcm6345-regulator";
  regmap = <&misc>;
  offset = <0x4c>;
  #address-cells = <1>;
  #size-cells = <0>;

  sar@0 {
regulator-name = "sar_power";
  };

  ipsec@1 {
regulator-name = "ipsec_power";
  };

  ...
};
  };

  ubus {
compatible = "brcm,ubus", "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges;

misc: syscon@10001800 {
  compatible = "syscon";
  reg = <0x10001800 0xd0>;
};
  };

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 11/11] watchdog: bcm63xx_wdt: Use brcm,bcm6345-wdt device tree binding

2015-12-01 Thread Simon Arlott
Add of_match_table for "brcm,bcm6345-wdt".

Use a NULL clock name when not on mach-bcm63xx so that the device tree
clock name does not have to be "periph".

Allow the watchdog to be selected on BMIPS_GENERIC and select the BCM6345
timer interrupt handler.

Signed-off-by: Simon Arlott 
---
 drivers/watchdog/Kconfig   |  3 ++-
 drivers/watchdog/bcm63xx_wdt.c | 14 +-
 2 files changed, 15 insertions(+), 2 deletions(-)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 6815b74..0c50add 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1272,8 +1272,9 @@ config OCTEON_WDT
 
 config BCM63XX_WDT
tristate "Broadcom BCM63xx hardware watchdog"
-   depends on BCM63XX
+   depends on BCM63XX || BMIPS_GENERIC
select WATCHDOG_CORE
+   select BCM6345_L2_TIMER_IRQ if BMIPS_GENERIC
help
  Watchdog driver for the built in watchdog hardware in Broadcom
  BCM63xx SoC.
diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c
index fa6c28b..4db4145 100644
--- a/drivers/watchdog/bcm63xx_wdt.c
+++ b/drivers/watchdog/bcm63xx_wdt.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -31,7 +32,11 @@
 
 #define PFX KBUILD_MODNAME
 
-#define WDT_CLK_NAME   "periph"
+#ifdef CONFIG_BCM63XX
+# define WDT_CLK_NAME  "periph"
+#else
+# define WDT_CLK_NAME  NULL
+#endif
 
 struct bcm63xx_wdt_hw {
struct watchdog_device wdd;
@@ -286,12 +291,19 @@ static void bcm63xx_wdt_shutdown(struct platform_device 
*pdev)
bcm63xx_wdt_stop(&hw->wdd);
 }
 
+static const struct of_device_id bcm63xx_wdt_dt_ids[] = {
+   { .compatible = "brcm,bcm6345-wdt" },
+   {}
+};
+MODULE_DEVICE_TABLE(of, bcm63xx_wdt_dt_ids);
+
 static struct platform_driver bcm63xx_wdt_driver = {
.probe  = bcm63xx_wdt_probe,
.remove = bcm63xx_wdt_remove,
.shutdown = bcm63xx_wdt_shutdown,
.driver = {
.name = "bcm63xx-wdt",
+   .of_match_table = bcm63xx_wdt_dt_ids,
}
 };
 
-- 
2.1.4


-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 10/11] watchdog: bcm63xx_wdt: Use bcm63xx_timer interrupt directly

2015-12-01 Thread Simon Arlott
There is only one user of bcm63xx_timer and that is the watchdog.
To allow the watchdog driver to be used on machine types other than
mach-bcm63xx, it needs to use an interrupt instead of a custom register
function.

Modify bcm63xx_timer to only disable the timers (so that they don't
interfere with the watchdog if an interrupt occurs) and remove its
exported functions.

Use the timer interrupt directly in bcm63xx_wdt.

Signed-off-by: Simon Arlott 
---
 arch/mips/bcm63xx/dev-wdt.c|   7 +
 arch/mips/bcm63xx/timer.c  | 181 +
 arch/mips/include/asm/mach-bcm63xx/bcm63xx_timer.h |  11 --
 drivers/watchdog/bcm63xx_wdt.c |  41 +++--
 4 files changed, 36 insertions(+), 204 deletions(-)
 delete mode 100644 arch/mips/include/asm/mach-bcm63xx/bcm63xx_timer.h

diff --git a/arch/mips/bcm63xx/dev-wdt.c b/arch/mips/bcm63xx/dev-wdt.c
index 2a2346a..a7a5497 100644
--- a/arch/mips/bcm63xx/dev-wdt.c
+++ b/arch/mips/bcm63xx/dev-wdt.c
@@ -17,6 +17,11 @@ static struct resource wdt_resources[] = {
.end= -1, /* filled at runtime */
.flags  = IORESOURCE_MEM,
},
+   {
+   .start  = -1, /* filled at runtime */
+   .end= -1, /* filled at runtime */
+   .flags  = IORESOURCE_IRQ,
+   },
 };
 
 static struct platform_device bcm63xx_wdt_device = {
@@ -32,6 +37,8 @@ int __init bcm63xx_wdt_register(void)
wdt_resources[0].end = wdt_resources[0].start;
wdt_resources[0].end += RSET_WDT_SIZE - 1;
 
+   wdt_resources[1].start = bcm63xx_get_irq_number(IRQ_TIMER);
+
return platform_device_register(&bcm63xx_wdt_device);
 }
 arch_initcall(bcm63xx_wdt_register);
diff --git a/arch/mips/bcm63xx/timer.c b/arch/mips/bcm63xx/timer.c
index 2110359..9c7b41a6 100644
--- a/arch/mips/bcm63xx/timer.c
+++ b/arch/mips/bcm63xx/timer.c
@@ -9,196 +9,23 @@
 #include 
 #include 
 #include 
-#include 
-#include 
-#include 
 #include 
 #include 
-#include 
 #include 
 
-static DEFINE_RAW_SPINLOCK(timer_reg_lock);
-static DEFINE_RAW_SPINLOCK(timer_data_lock);
-static struct clk *periph_clk;
-
-static struct timer_data {
-   void(*cb)(void *);
-   void*data;
-} timer_data[BCM63XX_TIMER_COUNT];
-
-static irqreturn_t timer_interrupt(int irq, void *dev_id)
-{
-   u32 stat;
-   int i;
-
-   raw_spin_lock(&timer_reg_lock);
-   stat = bcm_timer_readl(TIMER_IRQSTAT_REG);
-   bcm_timer_writel(stat, TIMER_IRQSTAT_REG);
-   raw_spin_unlock(&timer_reg_lock);
-
-   for (i = 0; i < BCM63XX_TIMER_COUNT; i++) {
-   if (!(stat & TIMER_IRQSTAT_TIMER_CAUSE(i)))
-   continue;
-
-   raw_spin_lock(&timer_data_lock);
-   if (!timer_data[i].cb) {
-   raw_spin_unlock(&timer_data_lock);
-   continue;
-   }
-
-   timer_data[i].cb(timer_data[i].data);
-   raw_spin_unlock(&timer_data_lock);
-   }
-
-   return IRQ_HANDLED;
-}
-
-int bcm63xx_timer_enable(int id)
-{
-   u32 reg;
-   unsigned long flags;
-
-   if (id >= BCM63XX_TIMER_COUNT)
-   return -EINVAL;
-
-   raw_spin_lock_irqsave(&timer_reg_lock, flags);
-
-   reg = bcm_timer_readl(TIMER_CTLx_REG(id));
-   reg |= TIMER_CTL_ENABLE_MASK;
-   bcm_timer_writel(reg, TIMER_CTLx_REG(id));
-
-   reg = bcm_timer_readl(TIMER_IRQSTAT_REG);
-   reg |= TIMER_IRQSTAT_TIMER_IR_EN(id);
-   bcm_timer_writel(reg, TIMER_IRQSTAT_REG);
-
-   raw_spin_unlock_irqrestore(&timer_reg_lock, flags);
-   return 0;
-}
-
-EXPORT_SYMBOL(bcm63xx_timer_enable);
-
-int bcm63xx_timer_disable(int id)
+static int bcm63xx_timer_init(void)
 {
u32 reg;
-   unsigned long flags;
-
-   if (id >= BCM63XX_TIMER_COUNT)
-   return -EINVAL;
-
-   raw_spin_lock_irqsave(&timer_reg_lock, flags);
-
-   reg = bcm_timer_readl(TIMER_CTLx_REG(id));
-   reg &= ~TIMER_CTL_ENABLE_MASK;
-   bcm_timer_writel(reg, TIMER_CTLx_REG(id));
-
-   reg = bcm_timer_readl(TIMER_IRQSTAT_REG);
-   reg &= ~TIMER_IRQSTAT_TIMER_IR_EN(id);
-   bcm_timer_writel(reg, TIMER_IRQSTAT_REG);
-
-   raw_spin_unlock_irqrestore(&timer_reg_lock, flags);
-   return 0;
-}
-
-EXPORT_SYMBOL(bcm63xx_timer_disable);
-
-int bcm63xx_timer_register(int id, void (*callback)(void *data), void *data)
-{
-   unsigned long flags;
-   int ret;
-
-   if (id >= BCM63XX_TIMER_COUNT || !callback)
-   return -EINVAL;
-
-   ret = 0;
-   raw_spin_lock_irqsave(&timer_data_lock, flags);
-   if (timer_data[id].cb) {
-   ret = -EBUSY;
-   goto out;
-   }
-
-   timer_data[id].cb = callback;
-   timer_data[id].data = data;
-
-out:
-   raw_spin_unlock_irq

[PATCH 09/11] watchdog: bcm63xx_wdt: Remove dependency on mach-bcm63xx functions/defines

2015-12-01 Thread Simon Arlott
The bcm_readl() and bcm_writel() functions are only defined for
mach-bcm63xx, replace them with __raw_readl() and raw_writel().

The register defines required for the watchdog are in a mach-bcm63xx
header file. Move them to include/linux/bcm63xx_wdt.h so that they are
also available on other machine types.

Signed-off-by: Simon Arlott 
---
 MAINTAINERS   |  1 +
 arch/mips/bcm63xx/prom.c  |  1 +
 arch/mips/bcm63xx/setup.c |  1 +
 arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h | 22 
 drivers/watchdog/bcm63xx_wdt.c| 25 +++
 include/linux/bcm63xx_wdt.h   | 22 
 6 files changed, 37 insertions(+), 35 deletions(-)
 create mode 100644 include/linux/bcm63xx_wdt.h

diff --git a/MAINTAINERS b/MAINTAINERS
index cd553a0..a381176 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2376,6 +2376,7 @@ F:arch/mips/boot/dts/brcm/bcm*.dts*
 F: drivers/irqchip/irq-bcm63*
 F: drivers/irqchip/irq-bcm7*
 F: drivers/irqchip/irq-brcmstb*
+F: include/linux/bcm63xx_wdt.h
 
 BROADCOM TG3 GIGABIT ETHERNET DRIVER
 M: Prashant Sreedharan 
diff --git a/arch/mips/bcm63xx/prom.c b/arch/mips/bcm63xx/prom.c
index 7019e29..d2800fb 100644
--- a/arch/mips/bcm63xx/prom.c
+++ b/arch/mips/bcm63xx/prom.c
@@ -6,6 +6,7 @@
  * Copyright (C) 2008 Maxime Bizon 
  */
 
+#include 
 #include 
 #include 
 #include 
diff --git a/arch/mips/bcm63xx/setup.c b/arch/mips/bcm63xx/setup.c
index 2be9caa..181402f 100644
--- a/arch/mips/bcm63xx/setup.c
+++ b/arch/mips/bcm63xx/setup.c
@@ -6,6 +6,7 @@
  * Copyright (C) 2008 Maxime Bizon 
  */
 
+#include 
 #include 
 #include 
 #include 
diff --git a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h 
b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
index 5035f09..16a745b 100644
--- a/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
+++ b/arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
@@ -441,28 +441,6 @@
 
 
 /*
- * _REG relative to RSET_WDT
- */
-
-/* Watchdog default count register */
-#define WDT_DEFVAL_REG 0x0
-
-/* Watchdog control register */
-#define WDT_CTL_REG0x4
-
-/* Watchdog control register constants */
-#define WDT_START_1(0xff00)
-#define WDT_START_2(0x00ff)
-#define WDT_STOP_1 (0xee00)
-#define WDT_STOP_2 (0x00ee)
-
-/* Watchdog reset length register */
-#define WDT_RSTLEN_REG 0x8
-
-/* Watchdog soft reset register (BCM6328 only) */
-#define WDT_SOFTRESET_REG  0xc
-
-/*
  * _REG relative to RSET_GPIO
  */
 
diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c
index 2312dc2..f409523 100644
--- a/drivers/watchdog/bcm63xx_wdt.c
+++ b/drivers/watchdog/bcm63xx_wdt.c
@@ -13,6 +13,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include 
 #include 
 #include 
 #include 
@@ -27,8 +28,6 @@
 #include 
 #include 
 
-#include 
-#include 
 #include 
 #include 
 
@@ -58,9 +57,9 @@ static int bcm63xx_wdt_start(struct watchdog_device *wdd)
unsigned long flags;
 
raw_spin_lock_irqsave(&hw->lock, flags);
-   bcm_writel(wdd->timeout * hw->clock_hz, hw->regs + WDT_DEFVAL_REG);
-   bcm_writel(WDT_START_1, hw->regs + WDT_CTL_REG);
-   bcm_writel(WDT_START_2, hw->regs + WDT_CTL_REG);
+   __raw_writel(wdd->timeout * hw->clock_hz, hw->regs + WDT_DEFVAL_REG);
+   __raw_writel(WDT_START_1, hw->regs + WDT_CTL_REG);
+   __raw_writel(WDT_START_2, hw->regs + WDT_CTL_REG);
hw->running = true;
raw_spin_unlock_irqrestore(&hw->lock, flags);
return 0;
@@ -72,8 +71,8 @@ static int bcm63xx_wdt_stop(struct watchdog_device *wdd)
unsigned long flags;
 
raw_spin_lock_irqsave(&hw->lock, flags);
-   bcm_writel(WDT_STOP_1, hw->regs + WDT_CTL_REG);
-   bcm_writel(WDT_STOP_2, hw->regs + WDT_CTL_REG);
+   __raw_writel(WDT_STOP_1, hw->regs + WDT_CTL_REG);
+   __raw_writel(WDT_STOP_2, hw->regs + WDT_CTL_REG);
hw->running = false;
raw_spin_unlock_irqrestore(&hw->lock, flags);
return 0;
@@ -108,10 +107,10 @@ static void bcm63xx_wdt_isr(void *data)
raw_spin_lock_irqsave(&hw->lock, flags);
if (!hw->running) {
/* Stop the watchdog as it shouldn't be running */
-   bcm_writel(WDT_STOP_1, hw->regs + WDT_CTL_REG);
-   bcm_writel(WDT_STOP_2, hw->regs + WDT_CTL_REG);
+   __raw_writel(WDT_STOP_1

[PATCH 08/11] watchdog: bcm63xx_wdt: Warn if the watchdog is currently running

2015-12-01 Thread Simon Arlott
Warn when the device is registered if the hardware watchdog is currently
running and report the remaining time left.

Signed-off-by: Simon Arlott 
---
 drivers/watchdog/bcm63xx_wdt.c | 23 ++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c
index ab4a794..2312dc2 100644
--- a/drivers/watchdog/bcm63xx_wdt.c
+++ b/drivers/watchdog/bcm63xx_wdt.c
@@ -14,6 +14,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -159,6 +160,8 @@ static int bcm63xx_wdt_probe(struct platform_device *pdev)
struct bcm63xx_wdt_hw *hw;
struct watchdog_device *wdd;
struct resource *r;
+   u32 timeleft1, timeleft2;
+   unsigned int timeleft;
int ret;
 
hw = devm_kzalloc(&pdev->dev, sizeof(*hw), GFP_KERNEL);
@@ -199,7 +202,6 @@ static int bcm63xx_wdt_probe(struct platform_device *pdev)
}
 
raw_spin_lock_init(&hw->lock);
-   hw->running = false;
 
wdd->parent = &pdev->dev;
wdd->ops = &bcm63xx_wdt_ops;
@@ -213,6 +215,23 @@ static int bcm63xx_wdt_probe(struct platform_device *pdev)
watchdog_init_timeout(wdd, 0, &pdev->dev);
watchdog_set_nowayout(wdd, nowayout);
 
+   /* Compare two reads of the time left value, 2 clock ticks apart */
+   rmb();
+   timeleft1 = __raw_readl(hw->regs + WDT_CTL_REG);
+   udelay(DIV_ROUND_UP(100, hw->clock_hz / 2));
+   /* Ensure the register is read twice */
+   rmb();
+   timeleft2 = __raw_readl(hw->regs + WDT_CTL_REG);
+
+   /* If the time left is changing, the watchdog is running */
+   if (timeleft1 != timeleft2) {
+   hw->running = true;
+   timeleft = bcm63xx_wdt_get_timeleft(wdd);
+   } else {
+   hw->running = false;
+   timeleft = 0;
+   }
+
ret = watchdog_register_device(wdd);
if (ret < 0) {
dev_err(&pdev->dev, "failed to register watchdog device\n");
@@ -230,6 +249,8 @@ static int bcm63xx_wdt_probe(struct platform_device *pdev)
dev_name(wdd->dev), hw->regs,
wdd->timeout, wdd->max_timeout);
 
+   if (hw->running)
+   dev_alert(wdd->dev, "running, reboot in %us\n", timeleft);
return 0;
 
 unregister_watchdog:
-- 
2.1.4


-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 07/11] watchdog: bcm63xx_wdt: Add get_timeleft function

2015-12-01 Thread Simon Arlott
Return the remaining time from the hardware control register.

Signed-off-by: Simon Arlott 
---
 drivers/watchdog/bcm63xx_wdt.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c
index 0a19731..ab4a794 100644
--- a/drivers/watchdog/bcm63xx_wdt.c
+++ b/drivers/watchdog/bcm63xx_wdt.c
@@ -78,6 +78,19 @@ static int bcm63xx_wdt_stop(struct watchdog_device *wdd)
return 0;
 }
 
+static unsigned int bcm63xx_wdt_get_timeleft(struct watchdog_device *wdd)
+{
+   struct bcm63xx_wdt_hw *hw = to_wdt_hw(wdd);
+   unsigned long flags;
+   u32 val;
+
+   raw_spin_lock_irqsave(&hw->lock, flags);
+   val = __raw_readl(hw->regs + WDT_CTL_REG);
+   val /= hw->clock_hz;
+   raw_spin_unlock_irqrestore(&hw->lock, flags);
+   return val;
+}
+
 static int bcm63xx_wdt_set_timeout(struct watchdog_device *wdd,
unsigned int timeout)
 {
@@ -132,6 +145,7 @@ static struct watchdog_ops bcm63xx_wdt_ops = {
.owner = THIS_MODULE,
.start = bcm63xx_wdt_start,
.stop = bcm63xx_wdt_stop,
+   .get_timeleft = bcm63xx_wdt_get_timeleft,
.set_timeout = bcm63xx_wdt_set_timeout,
 };
 
@@ -256,6 +270,7 @@ module_platform_driver(bcm63xx_wdt_driver);
 
 MODULE_AUTHOR("Miguel Gaio ");
 MODULE_AUTHOR("Florian Fainelli ");
+MODULE_AUTHOR("Simon Arlott");
 MODULE_DESCRIPTION("Driver for the Broadcom BCM63xx SoC watchdog");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:bcm63xx-wdt");
-- 
2.1.4


-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 06/11] watchdog: bcm63xx_wdt: Obtain watchdog clock HZ from "periph" clk

2015-12-01 Thread Simon Arlott
Instead of using a fixed clock HZ in the driver, obtain it from the
"periph" clk that the watchdog timer uses.

Signed-off-by: Simon Arlott 
Reviewed-by: Florian Fainelli 
---
 drivers/watchdog/bcm63xx_wdt.c | 36 +++-
 1 file changed, 31 insertions(+), 5 deletions(-)

diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c
index 2257924..0a19731 100644
--- a/drivers/watchdog/bcm63xx_wdt.c
+++ b/drivers/watchdog/bcm63xx_wdt.c
@@ -13,6 +13,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include 
 #include 
 #include 
 #include 
@@ -32,12 +33,14 @@
 
 #define PFX KBUILD_MODNAME
 
-#define WDT_HZ 5000/* Fclk */
+#define WDT_CLK_NAME   "periph"
 
 struct bcm63xx_wdt_hw {
struct watchdog_device wdd;
raw_spinlock_t lock;
void __iomem *regs;
+   struct clk *clk;
+   unsigned long clock_hz;
bool running;
 };
 
@@ -54,7 +57,7 @@ static int bcm63xx_wdt_start(struct watchdog_device *wdd)
unsigned long flags;
 
raw_spin_lock_irqsave(&hw->lock, flags);
-   bcm_writel(wdd->timeout * WDT_HZ, hw->regs + WDT_DEFVAL_REG);
+   bcm_writel(wdd->timeout * hw->clock_hz, hw->regs + WDT_DEFVAL_REG);
bcm_writel(WDT_START_1, hw->regs + WDT_CTL_REG);
bcm_writel(WDT_START_2, hw->regs + WDT_CTL_REG);
hw->running = true;
@@ -118,7 +121,7 @@ static void bcm63xx_wdt_isr(void *data)
die(PFX ": watchdog timer expired\n", get_irq_regs());
}
 
-   ms = timeleft / (WDT_HZ / 1000);
+   ms = timeleft / (hw->clock_hz / 1000);
dev_alert(hw->wdd.dev,
"warning timer fired, reboot in %ums\n", ms);
}
@@ -162,6 +165,25 @@ static int bcm63xx_wdt_probe(struct platform_device *pdev)
return -ENXIO;
}
 
+   hw->clk = devm_clk_get(&pdev->dev, WDT_CLK_NAME);
+   if (IS_ERR(hw->clk)) {
+   if (PTR_ERR(hw->clk) != -EPROBE_DEFER)
+   dev_err(&pdev->dev, "unable to request clock\n");
+   return PTR_ERR(hw->clk);
+   }
+
+   hw->clock_hz = clk_get_rate(hw->clk);
+   if (!hw->clock_hz) {
+   dev_err(&pdev->dev, "unable to fetch clock rate\n");
+   return -EINVAL;
+   }
+
+   ret = clk_prepare_enable(hw->clk);
+   if (ret) {
+   dev_err(&pdev->dev, "unable to enable clock\n");
+   return ret;
+   }
+
raw_spin_lock_init(&hw->lock);
hw->running = false;
 
@@ -169,7 +191,7 @@ static int bcm63xx_wdt_probe(struct platform_device *pdev)
wdd->ops = &bcm63xx_wdt_ops;
wdd->info = &bcm63xx_wdt_info;
wdd->min_timeout = 1;
-   wdd->max_timeout = 0x / WDT_HZ;
+   wdd->max_timeout = 0x / hw->clock_hz;
wdd->timeout = min(30U, wdd->max_timeout);
 
platform_set_drvdata(pdev, hw);
@@ -180,7 +202,7 @@ static int bcm63xx_wdt_probe(struct platform_device *pdev)
ret = watchdog_register_device(wdd);
if (ret < 0) {
dev_err(&pdev->dev, "failed to register watchdog device\n");
-   return ret;
+   goto disable_clk;
}
 
ret = bcm63xx_timer_register(TIMER_WDT_ID, bcm63xx_wdt_isr, hw);
@@ -198,6 +220,9 @@ static int bcm63xx_wdt_probe(struct platform_device *pdev)
 
 unregister_watchdog:
watchdog_unregister_device(wdd);
+
+disable_clk:
+   clk_disable_unprepare(hw->clk);
return ret;
 }
 
@@ -207,6 +232,7 @@ static int bcm63xx_wdt_remove(struct platform_device *pdev)
 
bcm63xx_timer_unregister(TIMER_WDT_ID);
watchdog_unregister_device(&hw->wdd);
+   clk_disable_unprepare(hw->clk);
return 0;
 }
 
-- 
2.1.4


-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 05/11] watchdog: bcm63xx_wdt: Use WATCHDOG_CORE

2015-12-01 Thread Simon Arlott
Convert bcm63xx_wdt to use WATCHDOG_CORE.

The default and maximum time constants that are only used once have been
moved to the initialisation of the struct watchdog_device.

Signed-off-by: Simon Arlott 
---
 drivers/watchdog/Kconfig   |   1 +
 drivers/watchdog/bcm63xx_wdt.c | 259 +
 2 files changed, 79 insertions(+), 181 deletions(-)

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 7a8a6c6..6815b74 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1273,6 +1273,7 @@ config OCTEON_WDT
 config BCM63XX_WDT
tristate "Broadcom BCM63xx hardware watchdog"
depends on BCM63XX
+   select WATCHDOG_CORE
help
  Watchdog driver for the built in watchdog hardware in Broadcom
  BCM63xx SoC.
diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c
index 3f55cba..2257924 100644
--- a/drivers/watchdog/bcm63xx_wdt.c
+++ b/drivers/watchdog/bcm63xx_wdt.c
@@ -13,20 +13,15 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include 
 #include 
-#include 
 #include 
 #include 
-#include 
 #include 
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
-#include 
 #include 
 #include 
 
@@ -38,53 +33,59 @@
 #define PFX KBUILD_MODNAME
 
 #define WDT_HZ 5000/* Fclk */
-#define WDT_DEFAULT_TIME   30  /* seconds */
-#define WDT_MAX_TIME   (0x / WDT_HZ)   /* seconds */
 
 struct bcm63xx_wdt_hw {
+   struct watchdog_device wdd;
raw_spinlock_t lock;
void __iomem *regs;
-   unsigned long inuse;
bool running;
 };
-static struct bcm63xx_wdt_hw bcm63xx_wdt_device;
 
-static int expect_close;
+#define to_wdt_hw(x) container_of(x, struct bcm63xx_wdt_hw, wdd)
 
-static int wdt_time = WDT_DEFAULT_TIME;
 static bool nowayout = WATCHDOG_NOWAYOUT;
 module_param(nowayout, bool, 0);
 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
 
-/* HW functions */
-static void bcm63xx_wdt_hw_start(void)
+static int bcm63xx_wdt_start(struct watchdog_device *wdd)
 {
+   struct bcm63xx_wdt_hw *hw = to_wdt_hw(wdd);
unsigned long flags;
 
-   raw_spin_lock_irqsave(&bcm63xx_wdt_device.lock, flags);
-   bcm_writel(wdt_time * WDT_HZ, bcm63xx_wdt_device.regs + WDT_DEFVAL_REG);
-   bcm_writel(WDT_START_1, bcm63xx_wdt_device.regs + WDT_CTL_REG);
-   bcm_writel(WDT_START_2, bcm63xx_wdt_device.regs + WDT_CTL_REG);
-   bcm63xx_wdt_device.running = true;
-   raw_spin_unlock_irqrestore(&bcm63xx_wdt_device.lock, flags);
+   raw_spin_lock_irqsave(&hw->lock, flags);
+   bcm_writel(wdd->timeout * WDT_HZ, hw->regs + WDT_DEFVAL_REG);
+   bcm_writel(WDT_START_1, hw->regs + WDT_CTL_REG);
+   bcm_writel(WDT_START_2, hw->regs + WDT_CTL_REG);
+   hw->running = true;
+   raw_spin_unlock_irqrestore(&hw->lock, flags);
+   return 0;
 }
 
-static void bcm63xx_wdt_hw_stop(void)
+static int bcm63xx_wdt_stop(struct watchdog_device *wdd)
 {
+   struct bcm63xx_wdt_hw *hw = to_wdt_hw(wdd);
unsigned long flags;
 
-   raw_spin_lock_irqsave(&bcm63xx_wdt_device.lock, flags);
-   bcm_writel(WDT_STOP_1, bcm63xx_wdt_device.regs + WDT_CTL_REG);
-   bcm_writel(WDT_STOP_2, bcm63xx_wdt_device.regs + WDT_CTL_REG);
-   bcm63xx_wdt_device.running = false;
-   raw_spin_unlock_irqrestore(&bcm63xx_wdt_device.lock, flags);
+   raw_spin_lock_irqsave(&hw->lock, flags);
+   bcm_writel(WDT_STOP_1, hw->regs + WDT_CTL_REG);
+   bcm_writel(WDT_STOP_2, hw->regs + WDT_CTL_REG);
+   hw->running = false;
+   raw_spin_unlock_irqrestore(&hw->lock, flags);
+   return 0;
+}
+
+static int bcm63xx_wdt_set_timeout(struct watchdog_device *wdd,
+   unsigned int timeout)
+{
+   wdd->timeout = timeout;
+   return 0;
 }
 
 /* The watchdog interrupt occurs when half the timeout is remaining */
 static void bcm63xx_wdt_isr(void *data)
 {
-   struct bcm63xx_wdt_hw *hw = &bcm63xx_wdt_device;
+   struct bcm63xx_wdt_hw *hw = data;
unsigned long flags;
 
raw_spin_lock_irqsave(&hw->lock, flags);
@@ -118,147 +119,36 @@ static void bcm63xx_wdt_isr(void *data)
}
 
ms = timeleft / (WDT_HZ / 1000);
-   pr_alert("warning timer fired, reboot in %ums\n", ms);
+   dev_alert(hw->wdd.dev,
+   "warning timer fired, reboot in %ums\n", ms);
}
raw_spin_unlock_irqrestore(&hw->lock, flags);
 }
 
-static int bcm63xx_wdt_settimeout(int new_time)
-{
-   if ((new_time <= 0) || (new_time > WDT_MAX_TIME))
-   return -EINVAL;
-
-   wdt_time = new_time;
-
-   return 0;
-}
-
-st

[PATCH 04/11] watchdog: bcm63xx_wdt: Handle hardware interrupt and remove software timer

2015-12-01 Thread Simon Arlott
There is a level triggered interrupt for the watchdog timer as part of
the bcm63xx_timer device. The interrupt occurs when the hardware watchdog
timer reaches 50% of the remaining time.

It is not possible to mask the interrupt within the bcm63xx_timer device.
To get around this limitation, handle the interrupt by restarting the
watchdog with the current remaining time (which will be half the previous
timeout) so that the interrupt occurs again at 1/4th, 1/8th, etc. of the
original timeout value until the watchdog forces a reboot.

The software timer was restarting the hardware watchdog with a 85 second
timeout until the software timer expired, and then causing a panic()
about 42.5 seconds later when the hardware interrupt occurred. The
hardware watchdog would not reboot until a further 42.5 seconds had
passed.

Remove the software timer and rely on the hardware timer directly,
reducing the maximum timeout from 256 seconds to 85 seconds
(2^32 / WDT_HZ).

Signed-off-by: Simon Arlott 
---
 drivers/watchdog/bcm63xx_wdt.c | 125 -
 1 file changed, 73 insertions(+), 52 deletions(-)

diff --git a/drivers/watchdog/bcm63xx_wdt.c b/drivers/watchdog/bcm63xx_wdt.c
index ab26fd9..3f55cba 100644
--- a/drivers/watchdog/bcm63xx_wdt.c
+++ b/drivers/watchdog/bcm63xx_wdt.c
@@ -3,6 +3,7 @@
  *
  *  Copyright (C) 2007, Miguel Gaio 
  *  Copyright (C) 2008, Florian Fainelli 
+ *  Copyright 2015 Simon Arlott
  *
  *  This program is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU General Public License
@@ -20,11 +21,10 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
-#include 
-#include 
 #include 
 #include 
 #include 
@@ -37,16 +37,17 @@
 
 #define PFX KBUILD_MODNAME
 
-#define WDT_HZ 5000 /* Fclk */
-#define WDT_DEFAULT_TIME   30  /* seconds */
-#define WDT_MAX_TIME   256 /* seconds */
+#define WDT_HZ 5000/* Fclk */
+#define WDT_DEFAULT_TIME   30  /* seconds */
+#define WDT_MAX_TIME   (0x / WDT_HZ)   /* seconds */
 
-static struct {
+struct bcm63xx_wdt_hw {
+   raw_spinlock_t lock;
void __iomem *regs;
-   struct timer_list timer;
unsigned long inuse;
-   atomic_t ticks;
-} bcm63xx_wdt_device;
+   bool running;
+};
+static struct bcm63xx_wdt_hw bcm63xx_wdt_device;
 
 static int expect_close;
 
@@ -59,48 +60,67 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once 
started (default="
 /* HW functions */
 static void bcm63xx_wdt_hw_start(void)
 {
-   bcm_writel(0xfffe, bcm63xx_wdt_device.regs + WDT_DEFVAL_REG);
+   unsigned long flags;
+
+   raw_spin_lock_irqsave(&bcm63xx_wdt_device.lock, flags);
+   bcm_writel(wdt_time * WDT_HZ, bcm63xx_wdt_device.regs + WDT_DEFVAL_REG);
bcm_writel(WDT_START_1, bcm63xx_wdt_device.regs + WDT_CTL_REG);
bcm_writel(WDT_START_2, bcm63xx_wdt_device.regs + WDT_CTL_REG);
+   bcm63xx_wdt_device.running = true;
+   raw_spin_unlock_irqrestore(&bcm63xx_wdt_device.lock, flags);
 }
 
 static void bcm63xx_wdt_hw_stop(void)
 {
+   unsigned long flags;
+
+   raw_spin_lock_irqsave(&bcm63xx_wdt_device.lock, flags);
bcm_writel(WDT_STOP_1, bcm63xx_wdt_device.regs + WDT_CTL_REG);
bcm_writel(WDT_STOP_2, bcm63xx_wdt_device.regs + WDT_CTL_REG);
+   bcm63xx_wdt_device.running = false;
+   raw_spin_unlock_irqrestore(&bcm63xx_wdt_device.lock, flags);
 }
 
+/* The watchdog interrupt occurs when half the timeout is remaining */
 static void bcm63xx_wdt_isr(void *data)
 {
-   struct pt_regs *regs = get_irq_regs();
-
-   die(PFX " fire", regs);
-}
-
-static void bcm63xx_timer_tick(unsigned long unused)
-{
-   if (!atomic_dec_and_test(&bcm63xx_wdt_device.ticks)) {
-   bcm63xx_wdt_hw_start();
-   mod_timer(&bcm63xx_wdt_device.timer, jiffies + HZ);
-   } else
-   pr_crit("watchdog will restart system\n");
-}
-
-static void bcm63xx_wdt_pet(void)
-{
-   atomic_set(&bcm63xx_wdt_device.ticks, wdt_time);
-}
-
-static void bcm63xx_wdt_start(void)
-{
-   bcm63xx_wdt_pet();
-   bcm63xx_timer_tick(0);
-}
+   struct bcm63xx_wdt_hw *hw = &bcm63xx_wdt_device;
+   unsigned long flags;
+
+   raw_spin_lock_irqsave(&hw->lock, flags);
+   if (!hw->running) {
+   /* Stop the watchdog as it shouldn't be running */
+   bcm_writel(WDT_STOP_1, hw->regs + WDT_CTL_REG);
+   bcm_writel(WDT_STOP_2, hw->regs + WDT_CTL_REG);
+   } else {
+   u32 timeleft = bcm_readl(hw->regs + WDT_CTL_REG);
+   u32 ms;
+
+   if (timeleft >= 2) {
+   /* The only way to clear this level triggered interrupt
+* without disrupting the normal running of the 

[PATCH 03/11] watchdog: Add brcm,bcm6345-wdt device tree binding

2015-12-01 Thread Simon Arlott
Add device tree binding for the BCM6345 watchdog.

This uses the BCM6345 timer for its warning interrupt.

Signed-off-by: Simon Arlott 
Acked-by: Rob Herring 
---
 .../bindings/watchdog/brcm,bcm6345-wdt.txt | 35 ++
 1 file changed, 35 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/watchdog/brcm,bcm6345-wdt.txt

diff --git a/Documentation/devicetree/bindings/watchdog/brcm,bcm6345-wdt.txt 
b/Documentation/devicetree/bindings/watchdog/brcm,bcm6345-wdt.txt
new file mode 100644
index 000..9d852d4
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/brcm,bcm6345-wdt.txt
@@ -0,0 +1,35 @@
+BCM6345 Watchdog timer
+
+Required properties:
+
+- compatible: should be "brcm,bcm63-wdt", "brcm,bcm6345-wdt"
+- reg: Specifies base physical address and size of the registers.
+- clocks: Specify the clock used for timing
+
+Optional properties:
+
+- interrupt-parent: phandle to the interrupt controller
+- interrupts: Specify the interrupt used for the watchdog timout warning
+- timeout-sec: Contains the default watchdog timeout in seconds
+
+Example:
+
+watchdog {
+   compatible = "brcm,bcm63168-wdt", "brcm,bcm6345-wdt";
+   reg = <0x109c 0x0c>;
+   clocks = <&periph_clk>;
+
+   interrupt-parent = <&timer>;
+   interrupts = <3>;
+   timeout-sec = <30>;
+};
+
+watchdog {
+   compatible = "brcm,bcm6318-wdt", "brcm,bcm6345-wdt";
+   reg = <0x1068 0x0c>;
+   clocks = <&periph_clk>;
+
+   interrupt-parent = <&timer>;
+   interrupts = <3>;
+   timeout-sec = <30>;
+};
-- 
2.1.4


-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 02/11] MIPS: bmips: Add bcm6345-l2-timer interrupt controller

2015-12-01 Thread Simon Arlott
Add the BCM6345/BCM6318 timer as an interrupt controller so that it can be
used by the watchdog to warn that its timer will expire soon.

Support for clocksource/clockevents is not implemented as the timer
interrupt is not per CPU (except on the BCM6318) and the MIPS clock is
better. This could be added later if required without changing the device
tree binding.

Signed-off-by: Simon Arlott 
---
 drivers/irqchip/Kconfig|   5 +
 drivers/irqchip/Makefile   |   1 +
 drivers/irqchip/irq-bcm6345-l2-timer.c | 386 +
 3 files changed, 392 insertions(+)
 create mode 100644 drivers/irqchip/irq-bcm6345-l2-timer.c

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index d307bb3..21c3d9b 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -70,6 +70,11 @@ config BCM6345_L1_IRQ
select GENERIC_IRQ_CHIP
select IRQ_DOMAIN
 
+config BCM6345_L2_TIMER_IRQ
+   bool
+   select GENERIC_IRQ_CHIP
+   select IRQ_DOMAIN
+
 config BCM7038_L1_IRQ
bool
select GENERIC_IRQ_CHIP
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index ded59cf..2687dea 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_XTENSA_MX)   += 
irq-xtensa-mx.o
 obj-$(CONFIG_IRQ_CROSSBAR) += irq-crossbar.o
 obj-$(CONFIG_SOC_VF610)+= irq-vf610-mscm-ir.o
 obj-$(CONFIG_BCM6345_L1_IRQ)   += irq-bcm6345-l1.o
+obj-$(CONFIG_BCM6345_L2_TIMER_IRQ) += irq-bcm6345-l2-timer.o
 obj-$(CONFIG_BCM7038_L1_IRQ)   += irq-bcm7038-l1.o
 obj-$(CONFIG_BCM7120_L2_IRQ)   += irq-bcm7120-l2.o
 obj-$(CONFIG_BRCMSTB_L2_IRQ)   += irq-brcmstb-l2.o
diff --git a/drivers/irqchip/irq-bcm6345-l2-timer.c 
b/drivers/irqchip/irq-bcm6345-l2-timer.c
new file mode 100644
index 000..f3acda7
--- /dev/null
+++ b/drivers/irqchip/irq-bcm6345-l2-timer.c
@@ -0,0 +1,386 @@
+/*
+ * Copyright 2015 Simon Arlott
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Based on arch/mips/bcm63xx/timer.c:
+ * Copyright (C) 2008 Maxime Bizon 
+ *
+ * Registers for SoCs with 4 timers: BCM6345, BCM6328, BCM6362, BCM6816,
+ *   BCM68220,BCM63168, BCM63268
+ *   0x02: Interrupt enable (u8)
+ *   0x03: Interrupt status (u8)
+ *   0x04: Timer 0 control
+ *   0x08: Timer 1 control
+ *   0x0c: Timer 2 control
+ *   0x10: Timer 0 count
+ *   0x14: Timer 1 count
+ *   0x18: Timer 2 count
+ *   0x1c+: Watchdog registers
+ *
+ * Registers for SoCs with 5 timers: BCM6318
+ *   0x00: Interrupt enable (u32)
+ *   0x04: Interrupt status (u32)
+ *   0x08: Timer 0 control
+ *   0x0c: Timer 1 control
+ *   0x10: Timer 2 control
+ *   0x14: Timer 3 control
+ *   0x18: Timer 0 count
+ *   0x1c: Timer 1 count
+ *   0x20: Timer 2 count
+ *   0x24: Timer 3 count
+ *   0x28+: Watchdog registers
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+enum timer_regs {
+   /* Interrupt enable register:
+*   1 bit per timer (without the watchdog)
+*/
+   TIMER_INT_ENABLE = 0,
+
+   /* Interrupt status register:
+*   1 bit per timer (plus the watchdog)
+*   Read for status
+*   Write bit to ack
+*/
+   TIMER_INT_STATUS,
+
+   /* Per-timer control register */
+   TIMER_CONTROL,
+
+   /* Per-timer count register */
+   TIMER_COUNT,
+
+
+   /* Number of registers in enum */
+   __TIMER_REGS_ENUM_SIZE
+};
+
+/* Watchdog interrupt is immediately after the timers */
+#define WATCHDOG_INT_BIT(x)(BIT((x)->variant.nr_timers))
+
+#define CONTROL_COUNTDOWN_MASK (0x3fff)
+#define CONTROL_RSTCNTCLR_MASK (1 << 30)
+#define CONTROL_ENABLE_MASK(1 << 31)
+
+#define COUNT_MASK (0x3fff)
+
+struct bcm6345_timer *timer;
+
+struct bcm6345_timer_variant {
+   unsigned int nr_timers;
+   u32 (*int_read)(struct bcm6345_timer *timer, int reg);
+   void (*int_write)(struct bcm6345_timer *timer, int reg, u32 val);
+   long regs[__TIMER_REGS_ENUM_SIZE];
+};
+
+struct bcm6345_timer {
+   raw_spinlock_t lock;
+   void __iomem *base;
+   unsigned int irq;
+   struct irq_domain *domain;
+
+   struct bcm6345_timer_variant variant;
+   u

[PATCH 01/11] clocksource: Add brcm,bcm6345-timer/brcm,bcm6318-timer device tree binding

2015-12-01 Thread Simon Arlott
Add device tree bindings for the BCM6345/BCM6318 timers. This is required
for the BCM6345 watchdog which needs to respond to one of the timer
interrupts.

Signed-off-by: Simon Arlott 
Acked-by: Rob Herring 
---
 .../bindings/timer/brcm,bcm6318-timer.txt  | 44 
 .../bindings/timer/brcm,bcm6345-timer.txt  | 47 ++
 2 files changed, 91 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/timer/brcm,bcm6318-timer.txt
 create mode 100644 
Documentation/devicetree/bindings/timer/brcm,bcm6345-timer.txt

diff --git a/Documentation/devicetree/bindings/timer/brcm,bcm6318-timer.txt 
b/Documentation/devicetree/bindings/timer/brcm,bcm6318-timer.txt
new file mode 100644
index 000..cf4be7e
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/brcm,bcm6318-timer.txt
@@ -0,0 +1,44 @@
+Broadcom BCM6318 Timer
+
+This block is a timer that is connected to multiple interrupts on the main
+interrupt controller and functions as a programmable interrupt controller for
+timer events. There is a main timer interrupt for all timers.
+
+- 4 independent timers with their own interrupt, and own maskable level
+  interrupt bit in the main timer interrupt
+
+- 1 watchdog timer with an unmaskable level interrupt bit in the main timer
+  interrupt
+
+- Contains one enable/status word pair
+
+- No atomic set/clear operations
+
+Required properties:
+
+- compatible: should be "brcm,bcm-timer", "brcm,bcm6318-timer"
+- reg: specifies the base physical address and size of the registers, excluding
+  the watchdog registers
+- interrupt-controller: identifies the node as an interrupt controller
+- #interrupt-cells: specifies the number of cells needed to encode an interrupt
+  source, should be 1.
+- interrupt-parent: specifies the phandle to the parent interrupt controller(s)
+  this one is cascaded from
+- interrupts: specifies the interrupt line(s) in the interrupt-parent 
controller
+  node for the main timer interrupt, followed by the individual timer
+  interrupts; valid values depend on the type of parent interrupt controller
+- clocks: phandle of timer reference clock (periph)
+
+Example:
+
+timer: timer@1040 {
+   compatible = "brcm,bcm63148-timer", "brcm,bcm6318-timer";
+   reg = <0x1040 0x28>;
+
+   interrupt-controller;
+   #interrupt-cells = <1>;
+
+   interrupt-parent = <&periph_intc>;
+   interrupts = <31>, <0>, <1>, <2>, <3>;
+   clock = <&periph_osc>;
+};
diff --git a/Documentation/devicetree/bindings/timer/brcm,bcm6345-timer.txt 
b/Documentation/devicetree/bindings/timer/brcm,bcm6345-timer.txt
new file mode 100644
index 000..03250dd
--- /dev/null
+++ b/Documentation/devicetree/bindings/timer/brcm,bcm6345-timer.txt
@@ -0,0 +1,47 @@
+Broadcom BCM6345 Timer
+
+This block is a timer that is connected to one interrupt on the main interrupt
+controller and functions as a programmable interrupt controller for timer
+events.
+
+- 3 independent timers with their own maskable level interrupt bit (but not
+  per CPU because there is only one parent interrupt and the timers share it)
+
+- 1 watchdog timer with an unmaskable level interrupt
+
+- Contains one enable/status word pair
+
+- No atomic set/clear operations
+
+The lack of per CPU ability of timers makes them unusable as a set of
+clockevent devices, otherwise they could be attached to the remaining
+interrupts.
+
+Required properties:
+
+- compatible: should be "brcm,bcm-timer", "brcm,bcm6345-timer"
+- reg: specifies the base physical address and size of the registers, excluding
+  the watchdog registers
+- interrupt-controller: identifies the node as an interrupt controller
+- #interrupt-cells: specifies the number of cells needed to encode an interrupt
+  source, should be 1.
+- interrupt-parent: specifies the phandle to the parent interrupt controller(s)
+  this one is cascaded from
+- interrupts: specifies the interrupt line(s) in the interrupt-parent 
controller
+  node for the timer interrupt; valid values depend on the type of parent
+  interrupt controller
+- clocks: phandle of timer reference clock (periph)
+
+Example:
+
+timer: timer@1080 {
+   compatible = "brcm,bcm63168-timer", "brcm,bcm6345-timer";
+   reg = <0x1080 0x1c>;
+
+   interrupt-controller;
+   #interrupt-cells = <1>;
+
+   interrupt-parent = <&periph_intc>;
+   interrupts = <0>;
+   clock·=·<&periph_osc>;
+};
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 2/2] reset: bcm63xx: Add support for the BCM63xx soft-reset controller

2015-11-30 Thread Simon Arlott
The BCM63xx contains a soft-reset controller activated by setting
a bit (that must previously have cleared).

Signed-off-by: Simon Arlott 
---
 MAINTAINERS   |   1 +
 drivers/reset/Kconfig |   9 +++
 drivers/reset/Makefile|   1 +
 drivers/reset/reset-bcm63xx.c | 134 ++
 4 files changed, 145 insertions(+)
 create mode 100644 drivers/reset/reset-bcm63xx.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 07613dd..55e493a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2378,6 +2378,7 @@ F:drivers/irqchip/irq-bcm63*
 F: drivers/irqchip/irq-bcm7*
 F: drivers/irqchip/irq-brcmstb*
 F: drivers/regulator/bcm63*
+F: drivers/reset/reset-bcm63*
 F: include/linux/bcm63xx_wdt.h
 
 BROADCOM TG3 GIGABIT ETHERNET DRIVER
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 0615f50..064dad2 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -12,4 +12,13 @@ menuconfig RESET_CONTROLLER
 
  If unsure, say no.
 
+if RESET_CONTROLLER
+
+config RESET_BCM63XX
+   bool "BCM63xx Reset Controller"
+   help
+ Support resetting of devices on BCM63xx boards.
+
+endif
+
 source "drivers/reset/sti/Kconfig"
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 85d5904..f6e2171 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -6,3 +6,4 @@ obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
 obj-$(CONFIG_ARCH_STI) += sti/
 obj-$(CONFIG_ARCH_ZYNQ) += reset-zynq.o
 obj-$(CONFIG_ATH79) += reset-ath79.o
+obj-$(CONFIG_RESET_BCM63XX) += reset-bcm63xx.o
diff --git a/drivers/reset/reset-bcm63xx.c b/drivers/reset/reset-bcm63xx.c
new file mode 100644
index 000..46db57f
--- /dev/null
+++ b/drivers/reset/reset-bcm63xx.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2015 Simon Arlott
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * Derived from reset-berlin.c:
+ * Copyright (C) 2014 Marvell Technology Group Ltd.
+ *
+ * Antoine Tenart 
+ * Sebastian Hesselbarth 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define to_bcm63xx_reset_priv(p) \
+   container_of((p), struct bcm63xx_reset_priv, rcdev)
+
+struct bcm63xx_reset_priv {
+   struct regmap *map;
+   u32 offset;
+   u32 mask; /* valid reset bits */
+   struct reset_controller_dev rcdev;
+   struct mutex mutex;
+};
+
+static int bcm63xx_reset_reset(struct reset_controller_dev *rcdev,
+   unsigned long id)
+{
+   struct bcm63xx_reset_priv *priv = to_bcm63xx_reset_priv(rcdev);
+
+   mutex_lock(&priv->mutex);
+   regmap_write_bits(priv->map, priv->offset, BIT(id), 0);
+   usleep_range(1, 2);
+   regmap_write_bits(priv->map, priv->offset, BIT(id), BIT(id));
+   usleep_range(1, 2);
+   mutex_unlock(&priv->mutex);
+
+   return 0;
+}
+
+static int bcm63xx_reset_xlate(struct reset_controller_dev *rcdev,
+   const struct of_phandle_args *reset_spec)
+{
+   struct bcm63xx_reset_priv *priv = to_bcm63xx_reset_priv(rcdev);
+
+   if (WARN_ON(reset_spec->args_count != rcdev->of_reset_n_cells))
+   return -EINVAL;
+
+   if (reset_spec->args[0] >= rcdev->nr_resets)
+   return -EINVAL;
+
+   if (!(BIT(reset_spec->args[0]) & priv->mask))
+   return -EINVAL;
+
+   return reset_spec->args[0];
+}
+
+
+static struct reset_control_ops bcm63xx_reset_ops = {
+   .reset = bcm63xx_reset_reset,
+};
+
+static int __init bcm63xx_reset_probe(struct platform_device *pdev)
+{
+   struct device_node *np = pdev->dev.of_node;
+   struct bcm63xx_reset_priv *priv;
+   int ret;
+
+   priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+   if (!priv)
+   return -ENOMEM;
+
+   mutex_init(&priv->mutex);
+
+   priv->map = syscon_regmap_lookup_by_phandle(np, "regmap");
+   if (IS_ERR(priv->map))
+   return PTR_ERR(priv->map);
+
+   if (of_property_read_u32(np, "offset", &priv->offset))
+   return -EINVAL;
+
+   /* valid reset bits */
+   if (of_property_read_u32(np, "mask", &priv->mask))
+   priv->mask = 0x;
+
+   priv->rcdev.owner = THIS_MODULE;
+   priv->rcdev.ops = &bcm63xx_reset_ops;
+   priv->rcdev.nr_resets = 32;
+   priv->rcdev.of_node = pdev->dev.of_node;
+   priv->rcdev.of_reset_n_cells = 1;
+   priv->rcdev.of_xlate = bcm63xx_reset_xlate;
+
+   ret = reset_controller_register(&priv->rcdev);
+   if (ret) {
+   dev_err(&pdev->dev,
+ 

[PATCH 1/2] reset: Add brcm,bcm63xx-reset device tree binding

2015-11-30 Thread Simon Arlott
Add device tree binding for the BCM63xx soft reset controller.

The BCM63xx contains a soft-reset controller activated by setting
a bit (that must previously have cleared).

Signed-off-by: Simon Arlott 
---
 .../bindings/reset/brcm,bcm63xx-reset.txt  | 37 ++
 1 file changed, 37 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/reset/brcm,bcm63xx-reset.txt

diff --git a/Documentation/devicetree/bindings/reset/brcm,bcm63xx-reset.txt 
b/Documentation/devicetree/bindings/reset/brcm,bcm63xx-reset.txt
new file mode 100644
index 000..48e9daf
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/brcm,bcm63xx-reset.txt
@@ -0,0 +1,37 @@
+BCM63xx reset controller
+
+The BCM63xx contains a basic soft reset controller in the perf register
+set which resets components using a bit in a register.
+
+Please also refer to reset.txt in this directory for common reset
+controller binding usage.
+
+Required properties:
+- compatible:  Should be "brcm,bcm-reset", "brcm,bcm63xx-reset"
+- regmap:  The register map phandle
+- offset:  Offset in the register map for the reset register (in bytes)
+- #reset-cells:Must be set to 1
+
+Optional properties:
+- mask:Mask of valid reset bits in the reset register (32 bit 
access)
+   (Defaults to all bits)
+
+Example:
+
+periph_soft_rst: reset-controller {
+   compatible = "brcm,bcm63168-reset", "brcm,bcm63xx-reset";
+   regmap = <&periph_cntl>;
+   offset = <0x10>;
+
+   #reset-cells = <1>;
+};
+
+usbh: usbphy@10002700 {
+   compatible = "brcm,bcm63168-usbh";
+   reg = <0x10002700 0x38>;
+   clocks = <&periph_clk 13>, <&timer_clk 18>;
+   resets = <&periph_soft_rst 6>;
+   power-supply = <&power_usbh>;
+   #phy-cells = <0>;
+};
+
-- 
2.1.4

-- 
Simon Arlott
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


  1   2   3   4   >