brintos

brintos / linux-shallow public Read only

0
0
Text · 17.8 KiB · 721df91 Raw
683 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2008-20104 *5 * - Kurt Van Dijck, EIA Electronics6 */7 8#include <linux/firmware.h>9#include <linux/sched/signal.h>10#include <asm/div64.h>11#include <asm/io.h>12 13#include "softing.h"14 15/*16 * low level DPRAM command.17 * Make sure that card->dpram[DPRAM_FCT_HOST] is preset18 */19static int _softing_fct_cmd(struct softing *card, int16_t cmd, uint16_t vector,20		const char *msg)21{22	int ret;23	unsigned long stamp;24 25	iowrite16(cmd, &card->dpram[DPRAM_FCT_PARAM]);26	iowrite8(vector >> 8, &card->dpram[DPRAM_FCT_HOST + 1]);27	iowrite8(vector, &card->dpram[DPRAM_FCT_HOST]);28	/* be sure to flush this to the card */29	wmb();30	stamp = jiffies + 1 * HZ;31	/* wait for card */32	do {33		/* DPRAM_FCT_HOST is _not_ aligned */34		ret = ioread8(&card->dpram[DPRAM_FCT_HOST]) +35			(ioread8(&card->dpram[DPRAM_FCT_HOST + 1]) << 8);36		/* don't have any cached variables */37		rmb();38		if (ret == RES_OK)39			/* read return-value now */40			return ioread16(&card->dpram[DPRAM_FCT_RESULT]);41 42		if ((ret != vector) || time_after(jiffies, stamp))43			break;44		/* process context => relax */45		usleep_range(500, 10000);46	} while (1);47 48	ret = (ret == RES_NONE) ? -ETIMEDOUT : -ECANCELED;49	dev_alert(&card->pdev->dev, "firmware %s failed (%i)\n", msg, ret);50	return ret;51}52 53static int softing_fct_cmd(struct softing *card, int16_t cmd, const char *msg)54{55	int ret;56 57	ret = _softing_fct_cmd(card, cmd, 0, msg);58	if (ret > 0) {59		dev_alert(&card->pdev->dev, "%s returned %u\n", msg, ret);60		ret = -EIO;61	}62	return ret;63}64 65int softing_bootloader_command(struct softing *card, int16_t cmd,66		const char *msg)67{68	int ret;69	unsigned long stamp;70 71	iowrite16(RES_NONE, &card->dpram[DPRAM_RECEIPT]);72	iowrite16(cmd, &card->dpram[DPRAM_COMMAND]);73	/* be sure to flush this to the card */74	wmb();75	stamp = jiffies + 3 * HZ;76	/* wait for card */77	do {78		ret = ioread16(&card->dpram[DPRAM_RECEIPT]);79		/* don't have any cached variables */80		rmb();81		if (ret == RES_OK)82			return 0;83		if (time_after(jiffies, stamp))84			break;85		/* process context => relax */86		usleep_range(500, 10000);87	} while (!signal_pending(current));88 89	ret = (ret == RES_NONE) ? -ETIMEDOUT : -ECANCELED;90	dev_alert(&card->pdev->dev, "bootloader %s failed (%i)\n", msg, ret);91	return ret;92}93 94static int fw_parse(const uint8_t **pmem, uint16_t *ptype, uint32_t *paddr,95		uint16_t *plen, const uint8_t **pdat)96{97	uint16_t checksum[2];98	const uint8_t *mem;99	const uint8_t *end;100 101	/*102	 * firmware records are a binary, unaligned stream composed of:103	 * uint16_t type;104	 * uint32_t addr;105	 * uint16_t len;106	 * uint8_t dat[len];107	 * uint16_t checksum;108	 * all values in little endian.109	 * We could define a struct for this, with __attribute__((packed)),110	 * but would that solve the alignment in _all_ cases (cfr. the111	 * struct itself may be an odd address)?112	 *113	 * I chose to use leXX_to_cpup() since this solves both114	 * endianness & alignment.115	 */116	mem = *pmem;117	*ptype = le16_to_cpup((void *)&mem[0]);118	*paddr = le32_to_cpup((void *)&mem[2]);119	*plen = le16_to_cpup((void *)&mem[6]);120	*pdat = &mem[8];121	/* verify checksum */122	end = &mem[8 + *plen];123	checksum[0] = le16_to_cpup((void *)end);124	for (checksum[1] = 0; mem < end; ++mem)125		checksum[1] += *mem;126	if (checksum[0] != checksum[1])127		return -EINVAL;128	/* increment */129	*pmem += 10 + *plen;130	return 0;131}132 133int softing_load_fw(const char *file, struct softing *card,134		__iomem uint8_t *dpram, unsigned int size, int offset)135{136	const struct firmware *fw;137	int ret;138	const uint8_t *mem, *end, *dat;139	uint16_t type, len;140	uint32_t addr;141	uint8_t *buf = NULL, *new_buf;142	int buflen = 0;143	int8_t type_end = 0;144 145	ret = request_firmware(&fw, file, &card->pdev->dev);146	if (ret < 0)147		return ret;148	dev_dbg(&card->pdev->dev, "%s, firmware(%s) got %u bytes"149		", offset %c0x%04x\n",150		card->pdat->name, file, (unsigned int)fw->size,151		(offset >= 0) ? '+' : '-', (unsigned int)abs(offset));152	/* parse the firmware */153	mem = fw->data;154	end = &mem[fw->size];155	/* look for header record */156	ret = fw_parse(&mem, &type, &addr, &len, &dat);157	if (ret < 0)158		goto failed;159	if (type != 0xffff)160		goto failed;161	if (strncmp("Structured Binary Format, Softing GmbH" , dat, len)) {162		ret = -EINVAL;163		goto failed;164	}165	/* ok, we had a header */166	while (mem < end) {167		ret = fw_parse(&mem, &type, &addr, &len, &dat);168		if (ret < 0)169			goto failed;170		if (type == 3) {171			/* start address, not used here */172			continue;173		} else if (type == 1) {174			/* eof */175			type_end = 1;176			break;177		} else if (type != 0) {178			ret = -EINVAL;179			goto failed;180		}181 182		if ((addr + len + offset) > size)183			goto failed;184		memcpy_toio(&dpram[addr + offset], dat, len);185		/* be sure to flush caches from IO space */186		mb();187		if (len > buflen) {188			/* align buflen */189			buflen = (len + (1024-1)) & ~(1024-1);190			new_buf = krealloc(buf, buflen, GFP_KERNEL);191			if (!new_buf) {192				ret = -ENOMEM;193				goto failed;194			}195			buf = new_buf;196		}197		/* verify record data */198		memcpy_fromio(buf, &dpram[addr + offset], len);199		if (memcmp(buf, dat, len)) {200			/* is not ok */201			dev_alert(&card->pdev->dev, "DPRAM readback failed\n");202			ret = -EIO;203			goto failed;204		}205	}206	if (!type_end)207		/* no end record seen */208		goto failed;209	ret = 0;210failed:211	kfree(buf);212	release_firmware(fw);213	if (ret < 0)214		dev_info(&card->pdev->dev, "firmware %s failed\n", file);215	return ret;216}217 218int softing_load_app_fw(const char *file, struct softing *card)219{220	const struct firmware *fw;221	const uint8_t *mem, *end, *dat;222	int ret, j;223	uint16_t type, len;224	uint32_t addr, start_addr = 0;225	unsigned int sum, rx_sum;226	int8_t type_end = 0, type_entrypoint = 0;227 228	ret = request_firmware(&fw, file, &card->pdev->dev);229	if (ret) {230		dev_alert(&card->pdev->dev, "request_firmware(%s) got %i\n",231			file, ret);232		return ret;233	}234	dev_dbg(&card->pdev->dev, "firmware(%s) got %lu bytes\n",235		file, (unsigned long)fw->size);236	/* parse the firmware */237	mem = fw->data;238	end = &mem[fw->size];239	/* look for header record */240	ret = fw_parse(&mem, &type, &addr, &len, &dat);241	if (ret)242		goto failed;243	ret = -EINVAL;244	if (type != 0xffff) {245		dev_alert(&card->pdev->dev, "firmware starts with type 0x%x\n",246			type);247		goto failed;248	}249	if (strncmp("Structured Binary Format, Softing GmbH", dat, len)) {250		dev_alert(&card->pdev->dev, "firmware string '%.*s' fault\n",251				len, dat);252		goto failed;253	}254	/* ok, we had a header */255	while (mem < end) {256		ret = fw_parse(&mem, &type, &addr, &len, &dat);257		if (ret)258			goto failed;259 260		if (type == 3) {261			/* start address */262			start_addr = addr;263			type_entrypoint = 1;264			continue;265		} else if (type == 1) {266			/* eof */267			type_end = 1;268			break;269		} else if (type != 0) {270			dev_alert(&card->pdev->dev,271					"unknown record type 0x%04x\n", type);272			ret = -EINVAL;273			goto failed;274		}275 276		/* regular data */277		for (sum = 0, j = 0; j < len; ++j)278			sum += dat[j];279		/* work in 16bit (target) */280		sum &= 0xffff;281 282		memcpy_toio(&card->dpram[card->pdat->app.offs], dat, len);283		iowrite32(card->pdat->app.offs + card->pdat->app.addr,284				&card->dpram[DPRAM_COMMAND + 2]);285		iowrite32(addr, &card->dpram[DPRAM_COMMAND + 6]);286		iowrite16(len, &card->dpram[DPRAM_COMMAND + 10]);287		iowrite8(1, &card->dpram[DPRAM_COMMAND + 12]);288		ret = softing_bootloader_command(card, 1, "loading app.");289		if (ret < 0)290			goto failed;291		/* verify checksum */292		rx_sum = ioread16(&card->dpram[DPRAM_RECEIPT + 2]);293		if (rx_sum != sum) {294			dev_alert(&card->pdev->dev, "SRAM seems to be damaged"295				", wanted 0x%04x, got 0x%04x\n", sum, rx_sum);296			ret = -EIO;297			goto failed;298		}299	}300	if (!type_end || !type_entrypoint)301		goto failed;302	/* start application in card */303	iowrite32(start_addr, &card->dpram[DPRAM_COMMAND + 2]);304	iowrite8(1, &card->dpram[DPRAM_COMMAND + 6]);305	ret = softing_bootloader_command(card, 3, "start app.");306	if (ret < 0)307		goto failed;308	ret = 0;309failed:310	release_firmware(fw);311	if (ret < 0)312		dev_info(&card->pdev->dev, "firmware %s failed\n", file);313	return ret;314}315 316static int softing_reset_chip(struct softing *card)317{318	int ret;319 320	do {321		/* reset chip */322		iowrite8(0, &card->dpram[DPRAM_RESET_RX_FIFO]);323		iowrite8(0, &card->dpram[DPRAM_RESET_RX_FIFO+1]);324		iowrite8(1, &card->dpram[DPRAM_RESET]);325		iowrite8(0, &card->dpram[DPRAM_RESET+1]);326 327		ret = softing_fct_cmd(card, 0, "reset_can");328		if (!ret)329			break;330		if (signal_pending(current))331			/* don't wait any longer */332			break;333	} while (1);334	card->tx.pending = 0;335	return ret;336}337 338int softing_chip_poweron(struct softing *card)339{340	int ret;341	/* sync */342	ret = _softing_fct_cmd(card, 99, 0x55, "sync-a");343	if (ret < 0)344		goto failed;345 346	ret = _softing_fct_cmd(card, 99, 0xaa, "sync-b");347	if (ret < 0)348		goto failed;349 350	ret = softing_reset_chip(card);351	if (ret < 0)352		goto failed;353	/* get_serial */354	ret = softing_fct_cmd(card, 43, "get_serial_number");355	if (ret < 0)356		goto failed;357	card->id.serial = ioread32(&card->dpram[DPRAM_FCT_PARAM]);358	/* get_version */359	ret = softing_fct_cmd(card, 12, "get_version");360	if (ret < 0)361		goto failed;362	card->id.fw_version = ioread16(&card->dpram[DPRAM_FCT_PARAM + 2]);363	card->id.hw_version = ioread16(&card->dpram[DPRAM_FCT_PARAM + 4]);364	card->id.license = ioread16(&card->dpram[DPRAM_FCT_PARAM + 6]);365	card->id.chip[0] = ioread16(&card->dpram[DPRAM_FCT_PARAM + 8]);366	card->id.chip[1] = ioread16(&card->dpram[DPRAM_FCT_PARAM + 10]);367	return 0;368failed:369	return ret;370}371 372static void softing_initialize_timestamp(struct softing *card)373{374	uint64_t ovf;375 376	card->ts_ref = ktime_get();377 378	/* 16MHz is the reference */379	ovf = 0x100000000ULL * 16;380	do_div(ovf, card->pdat->freq ?: 16);381 382	card->ts_overflow = ktime_add_us(0, ovf);383}384 385ktime_t softing_raw2ktime(struct softing *card, u32 raw)386{387	uint64_t rawl;388	ktime_t now, real_offset;389	ktime_t target;390	ktime_t tmp;391 392	now = ktime_get();393	real_offset = ktime_sub(ktime_get_real(), now);394 395	/* find nsec from card */396	rawl = raw * 16;397	do_div(rawl, card->pdat->freq ?: 16);398	target = ktime_add_us(card->ts_ref, rawl);399	/* test for overflows */400	tmp = ktime_add(target, card->ts_overflow);401	while (unlikely(ktime_to_ns(tmp) > ktime_to_ns(now))) {402		card->ts_ref = ktime_add(card->ts_ref, card->ts_overflow);403		target = tmp;404		tmp = ktime_add(target, card->ts_overflow);405	}406	return ktime_add(target, real_offset);407}408 409static inline int softing_error_reporting(struct net_device *netdev)410{411	struct softing_priv *priv = netdev_priv(netdev);412 413	return (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)414		? 1 : 0;415}416 417int softing_startstop(struct net_device *dev, int up)418{419	int ret;420	struct softing *card;421	struct softing_priv *priv;422	struct net_device *netdev;423	int bus_bitmask_start;424	int j, error_reporting;425	struct can_frame msg;426	const struct can_bittiming *bt;427 428	priv = netdev_priv(dev);429	card = priv->card;430 431	if (!card->fw.up)432		return -EIO;433 434	ret = mutex_lock_interruptible(&card->fw.lock);435	if (ret)436		return ret;437 438	bus_bitmask_start = 0;439	if (up)440		/* prepare to start this bus as well */441		bus_bitmask_start |= (1 << priv->index);442	/* bring netdevs down */443	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {444		netdev = card->net[j];445		if (!netdev)446			continue;447		priv = netdev_priv(netdev);448 449		if (dev != netdev)450			netif_stop_queue(netdev);451 452		if (netif_running(netdev)) {453			if (dev != netdev)454				bus_bitmask_start |= (1 << j);455			priv->tx.pending = 0;456			priv->tx.echo_put = 0;457			priv->tx.echo_get = 0;458			/*459			 * this bus' may just have called open_candev()460			 * which is rather stupid to call close_candev()461			 * already462			 * but we may come here from busoff recovery too463			 * in which case the echo_skb _needs_ flushing too.464			 * just be sure to call open_candev() again465			 */466			close_candev(netdev);467		}468		priv->can.state = CAN_STATE_STOPPED;469	}470	card->tx.pending = 0;471 472	softing_enable_irq(card, 0);473	ret = softing_reset_chip(card);474	if (ret)475		goto failed;476	if (!bus_bitmask_start)477		/* no buses to be brought up */478		goto card_done;479 480	if ((bus_bitmask_start & 1) && (bus_bitmask_start & 2)481			&& (softing_error_reporting(card->net[0])482				!= softing_error_reporting(card->net[1]))) {483		dev_alert(&card->pdev->dev,484				"err_reporting flag differs for buses\n");485		goto invalid;486	}487	error_reporting = 0;488	if (bus_bitmask_start & 1) {489		netdev = card->net[0];490		priv = netdev_priv(netdev);491		error_reporting += softing_error_reporting(netdev);492		/* init chip 1 */493		bt = &priv->can.bittiming;494		iowrite16(bt->brp, &card->dpram[DPRAM_FCT_PARAM + 2]);495		iowrite16(bt->sjw, &card->dpram[DPRAM_FCT_PARAM + 4]);496		iowrite16(bt->phase_seg1 + bt->prop_seg,497				&card->dpram[DPRAM_FCT_PARAM + 6]);498		iowrite16(bt->phase_seg2, &card->dpram[DPRAM_FCT_PARAM + 8]);499		iowrite16((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 1 : 0,500				&card->dpram[DPRAM_FCT_PARAM + 10]);501		ret = softing_fct_cmd(card, 1, "initialize_chip[0]");502		if (ret < 0)503			goto failed;504		/* set mode */505		iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 2]);506		iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 4]);507		ret = softing_fct_cmd(card, 3, "set_mode[0]");508		if (ret < 0)509			goto failed;510		/* set filter */511		/* 11bit id & mask */512		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 2]);513		iowrite16(0x07ff, &card->dpram[DPRAM_FCT_PARAM + 4]);514		/* 29bit id.lo & mask.lo & id.hi & mask.hi */515		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 6]);516		iowrite16(0xffff, &card->dpram[DPRAM_FCT_PARAM + 8]);517		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 10]);518		iowrite16(0x1fff, &card->dpram[DPRAM_FCT_PARAM + 12]);519		ret = softing_fct_cmd(card, 7, "set_filter[0]");520		if (ret < 0)521			goto failed;522		/* set output control */523		iowrite16(priv->output, &card->dpram[DPRAM_FCT_PARAM + 2]);524		ret = softing_fct_cmd(card, 5, "set_output[0]");525		if (ret < 0)526			goto failed;527	}528	if (bus_bitmask_start & 2) {529		netdev = card->net[1];530		priv = netdev_priv(netdev);531		error_reporting += softing_error_reporting(netdev);532		/* init chip2 */533		bt = &priv->can.bittiming;534		iowrite16(bt->brp, &card->dpram[DPRAM_FCT_PARAM + 2]);535		iowrite16(bt->sjw, &card->dpram[DPRAM_FCT_PARAM + 4]);536		iowrite16(bt->phase_seg1 + bt->prop_seg,537				&card->dpram[DPRAM_FCT_PARAM + 6]);538		iowrite16(bt->phase_seg2, &card->dpram[DPRAM_FCT_PARAM + 8]);539		iowrite16((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 1 : 0,540				&card->dpram[DPRAM_FCT_PARAM + 10]);541		ret = softing_fct_cmd(card, 2, "initialize_chip[1]");542		if (ret < 0)543			goto failed;544		/* set mode2 */545		iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 2]);546		iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 4]);547		ret = softing_fct_cmd(card, 4, "set_mode[1]");548		if (ret < 0)549			goto failed;550		/* set filter2 */551		/* 11bit id & mask */552		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 2]);553		iowrite16(0x07ff, &card->dpram[DPRAM_FCT_PARAM + 4]);554		/* 29bit id.lo & mask.lo & id.hi & mask.hi */555		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 6]);556		iowrite16(0xffff, &card->dpram[DPRAM_FCT_PARAM + 8]);557		iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 10]);558		iowrite16(0x1fff, &card->dpram[DPRAM_FCT_PARAM + 12]);559		ret = softing_fct_cmd(card, 8, "set_filter[1]");560		if (ret < 0)561			goto failed;562		/* set output control2 */563		iowrite16(priv->output, &card->dpram[DPRAM_FCT_PARAM + 2]);564		ret = softing_fct_cmd(card, 6, "set_output[1]");565		if (ret < 0)566			goto failed;567	}568 569	/* enable_error_frame570	 *571	 * Error reporting is switched off at the moment since572	 * the receiving of them is not yet 100% verified573	 * This should be enabled sooner or later574	 */575	if (0 && error_reporting) {576		ret = softing_fct_cmd(card, 51, "enable_error_frame");577		if (ret < 0)578			goto failed;579	}580 581	/* initialize interface */582	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 2]);583	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 4]);584	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 6]);585	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 8]);586	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 10]);587	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 12]);588	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 14]);589	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 16]);590	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 18]);591	iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 20]);592	ret = softing_fct_cmd(card, 17, "initialize_interface");593	if (ret < 0)594		goto failed;595	/* enable_fifo */596	ret = softing_fct_cmd(card, 36, "enable_fifo");597	if (ret < 0)598		goto failed;599	/* enable fifo tx ack */600	ret = softing_fct_cmd(card, 13, "fifo_tx_ack[0]");601	if (ret < 0)602		goto failed;603	/* enable fifo tx ack2 */604	ret = softing_fct_cmd(card, 14, "fifo_tx_ack[1]");605	if (ret < 0)606		goto failed;607	/* start_chip */608	ret = softing_fct_cmd(card, 11, "start_chip");609	if (ret < 0)610		goto failed;611	iowrite8(0, &card->dpram[DPRAM_INFO_BUSSTATE]);612	iowrite8(0, &card->dpram[DPRAM_INFO_BUSSTATE2]);613	if (card->pdat->generation < 2) {614		iowrite8(0, &card->dpram[DPRAM_V2_IRQ_TOHOST]);615		/* flush the DPRAM caches */616		wmb();617	}618 619	softing_initialize_timestamp(card);620 621	/*622	 * do socketcan notifications/status changes623	 * from here, no errors should occur, or the failed: part624	 * must be reviewed625	 */626	memset(&msg, 0, sizeof(msg));627	msg.can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED;628	msg.len = CAN_ERR_DLC;629	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {630		if (!(bus_bitmask_start & (1 << j)))631			continue;632		netdev = card->net[j];633		if (!netdev)634			continue;635		priv = netdev_priv(netdev);636		priv->can.state = CAN_STATE_ERROR_ACTIVE;637		open_candev(netdev);638		if (dev != netdev) {639			/* notify other buses on the restart */640			softing_netdev_rx(netdev, &msg, 0);641			++priv->can.can_stats.restarts;642		}643		netif_wake_queue(netdev);644	}645 646	/* enable interrupts */647	ret = softing_enable_irq(card, 1);648	if (ret)649		goto failed;650card_done:651	mutex_unlock(&card->fw.lock);652	return 0;653invalid:654	ret = -EINVAL;655failed:656	softing_enable_irq(card, 0);657	softing_reset_chip(card);658	mutex_unlock(&card->fw.lock);659	/* bring all other interfaces down */660	for (j = 0; j < ARRAY_SIZE(card->net); ++j) {661		netdev = card->net[j];662		if (!netdev)663			continue;664		dev_close(netdev);665	}666	return ret;667}668 669int softing_default_output(struct net_device *netdev)670{671	struct softing_priv *priv = netdev_priv(netdev);672	struct softing *card = priv->card;673 674	switch (priv->chip) {675	case 1000:676		return (card->pdat->generation < 2) ? 0xfb : 0xfa;677	case 5:678		return 0x60;679	default:680		return 0x40;681	}682}683