diff --git a/drivers/net/lora/dev.c b/drivers/net/lora/dev.c
index 0d4823de8c06..62dbe21668b0 100644
--- a/drivers/net/lora/dev.c
+++ b/drivers/net/lora/dev.c
@@ -11,8 +11,6 @@
 #include <linux/lora/skb.h>
 #include <net/rtnetlink.h>
 
-#define LORA_MTU 256 /* XXX */
-
 struct sk_buff *alloc_lora_skb(struct net_device *dev, u8 **data)
 {
 	struct sk_buff *skb;
diff --git a/drivers/net/lora/sx1301.c b/drivers/net/lora/sx1301.c
index 9bcbb967f307..fed6d6201bf3 100644
--- a/drivers/net/lora/sx1301.c
+++ b/drivers/net/lora/sx1301.c
@@ -584,7 +584,7 @@ static int sx1301_load_tx_gain_lut(struct sx1301_priv *priv)
 	return ret;
 };
 
-static int sx1301_tx(struct sx1301_priv *priv, void *data, int len)
+static int sx1301_tx(struct sx1301_priv *priv, struct lora_frame *frame)
 {
 	int ret, i;
 	u8 buff[256 + 16];
@@ -617,11 +617,67 @@ static int sx1301_tx(struct sx1301_priv *priv, void *data, int len)
 	hdr->tx_power = 15; /* HACK power entry 15 */
 
 	hdr->u.lora.crc16_en = 1; /* Enable CRC16 */
-	hdr->u.lora.cr = 1; /* CR 4/5 */
-	hdr->u.lora.sf = 7; /* SF7 */
-	hdr->u.lora.payload_len = len; /* Set the data len to the skb len */
+
+	switch (frame->cr) {
+	case LORA_CR_4_5:
+		hdr->u.lora.cr = 1; /* CR 4/5 */
+		break;
+	case LORA_CR_4_6:
+		hdr->u.lora.cr = 2; /* CR 4/6 */
+		break;
+	case LORA_CR_4_7:
+		hdr->u.lora.cr = 3; /* CR 4/7 */
+		break;
+	case LORA_CR_4_8:
+		hdr->u.lora.cr = 4; /* CR 4/8 */
+		break;
+	default:
+		return -ENXIO;
+	}
+
+	switch (frame->sf) {
+	case LORA_SF_6:
+		hdr->u.lora.sf = 6; /* SF6 */
+		break;
+	case LORA_SF_7:
+		hdr->u.lora.sf = 7; /* SF7 */
+		break;
+	case LORA_SF_8:
+		hdr->u.lora.sf = 8; /* SF8 */
+		break;
+	case LORA_SF_9:
+		hdr->u.lora.sf = 9; /* SF9 */
+		break;
+	case LORA_SF_10:
+		hdr->u.lora.sf = 10; /* SF10 */
+		break;
+	case LORA_SF_11:
+		hdr->u.lora.sf = 11; /* SF11 */
+		break;
+	case LORA_SF_12:
+		hdr->u.lora.sf = 12; /* SF12 */
+		break;
+	default:
+		return -ENXIO;
+	}
+
+	hdr->u.lora.payload_len = frame->len; /* Set the data length */
 	hdr->u.lora.implicit_header = 0; /* No implicit header */
-	hdr->u.lora.mod_bw = 0; /* Set 125KHz BW */
+
+	switch (frame->bw) {
+	case LORA_BW_125KHZ:
+		hdr->u.lora.mod_bw = 0; /* 125KHz BW */
+		break;
+	case LORA_BW_250KHZ:
+		hdr->u.lora.mod_bw = 1; /* 250KHz BW */
+		break;
+	case LORA_BW_500KHZ:
+		hdr->u.lora.mod_bw = 2; /* 500KHz BW */
+		break;
+	default:
+		return -ENXIO;
+	}
+
 	hdr->u.lora.ppm_offset = 0; /* TODO no ppm offset? */
 	hdr->u.lora.invert_pol = 0; /* TODO set no inverted polarity */
 
@@ -632,7 +688,7 @@ static int sx1301_tx(struct sx1301_priv *priv, void *data, int len)
 
 	/* Copy the TX data into the buffer ready to go */
 
-	memcpy((void *)&buff[16], data, len);
+	memcpy((void *)&buff[16], frame->data, frame->len);
 
 	/* Reset any transmissions */
 	ret = regmap_write(priv->regmap, SX1301_TX_TRIG, 0);
@@ -644,7 +700,7 @@ static int sx1301_tx(struct sx1301_priv *priv, void *data, int len)
 	if (ret)
 		return ret;
 	ret = regmap_noinc_write(priv->regmap, SX1301_TX_DATA_BUF_DATA, buff,
-				 len + 16);
+				 frame->len + 16);
 	if (ret)
 		return ret;
 
@@ -653,8 +709,8 @@ static int sx1301_tx(struct sx1301_priv *priv, void *data, int len)
 	if (ret)
 		return ret;
 
-	dev_dbg(priv->dev, "Transmitting packet of size %d: ", len);
-	for (i = 0; i < len + 16; i++)
+	dev_dbg(priv->dev, "Transmitting packet of size %d: ", frame->len);
+	for (i = 0; i < frame->len + 16; i++)
 		dev_dbg(priv->dev, "%X", buff[i]);
 
 	return ret;
@@ -683,17 +739,18 @@ static void sx1301_tx_work_handler(struct work_struct *ws)
 	struct sx1301_priv *priv = container_of(ws, struct sx1301_priv,
 						tx_work);
 	struct net_device *netdev = dev_get_drvdata(priv->dev);
+	struct lora_frame *frame = (struct lora_frame *)priv->tx_skb->data;
 	int ret;
 
 	netdev_dbg(netdev, "%s\n", __func__);
 
 	if (priv->tx_skb) {
-		ret = sx1301_tx(priv, priv->tx_skb->data, priv->tx_skb->len);
+		ret = sx1301_tx(priv, frame);
 		if (ret) {
 			netdev->stats.tx_errors++;
 		} else {
 			netdev->stats.tx_packets++;
-			netdev->stats.tx_bytes += priv->tx_skb->len;
+			netdev->stats.tx_bytes += frame->len;
 		}
 
 		if (!(netdev->flags & IFF_ECHO) ||
diff --git a/include/uapi/linux/lora.h b/include/uapi/linux/lora.h
index 4ff00b9c3c20..d675025d2a6e 100644
--- a/include/uapi/linux/lora.h
+++ b/include/uapi/linux/lora.h
@@ -21,4 +21,50 @@ struct sockaddr_lora {
 	} lora_addr;
 };
 
+#define LORA_MAX_DLEN	256
+
+enum lora_bw {
+	LORA_BW_125KHZ,
+	LORA_BW_250KHZ,
+	LORA_BW_500KHZ,
+};
+
+enum lora_cr {
+	LORA_CR_4_5,
+	LORA_CR_4_6,
+	LORA_CR_4_7,
+	LORA_CR_4_8,
+};
+
+enum lora_sf {
+	LORA_SF_6,
+	LORA_SF_7,
+	LORA_SF_8,
+	LORA_SF_9,
+	LORA_SF_10,
+	LORA_SF_11,
+	LORA_SF_12,
+};
+
+/**
+ * struct lora_frame - LoRa frame structure
+ * @freq: Frequency of LoRa transmission in Hz
+ * @power: Power of transmission in dBm
+ * @bw:  bandwidth, 125, 250 or 500 KHz
+ * @cr:  coding rate, 4/5 to 4/8
+ * @sf:  spreading factor from SF6 to 12
+ * @data:   LoRa frame payload (up to LORA_MAX_DLEN byte)
+ */
+struct lora_frame {
+	__u32		freq; /* transmission frequency in Hz */
+	__u8		power; /* transmission power in dBm */
+	enum lora_bw	bw; /* bandwidth */
+	enum lora_cr	cr; /* coding rate */
+	enum lora_sf	sf; /* spreading factor */
+	__u8		len;
+	__u8		data[LORA_MAX_DLEN] __attribute__((aligned(8)));
+};
+
+#define LORA_MTU (sizeof(struct lora_frame))
+
 #endif /* _UAPI_LINUX_LORA_H */
